Jason Swett
Jason Swett

Reputation: 45074

Is there a better way to write this function?

I have the following Common Lisp function:

(defun get-positions (marker)
  (let ((result nil))
    (dotimes (i (length board))
      (if (eq (nth i board) marker)
          (push i result)))
    (nreverse result)))

Here's what board is and here's the output of the function:

CL-USER> board
(X X O NIL NIL NIL NIL NIL NIL)
CL-USER> (get-positions 'x)
(0 1)

It seems like the function I wrote might be a little verbose. Is there a more concise way to write it?

Upvotes: 0

Views: 101

Answers (1)

Gareth Rees
Gareth Rees

Reputation: 65854

I'd write it like this, passing in the list to be searched rather than using the global variable board. I'd also add a docstring, and since using eq for comparison seems rather arbitrary, I'd make it a keyword argument so you could supply = for numeric comparison or equal for strings:

(defun get-positions (x list &key (test #'eq))
  "Return list of indexes of positions where X appears in LIST.
Keyword :test specifies the comparison function (default: EQ)."
  (loop for y in list
        for i upfrom 0
        if (funcall test x y) collect i))

(get-positions 'x '(x x nil nil x nil x))
  ==> (0 1 4 6)

Upvotes: 7

Related Questions