Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>First, you are still in <em>imperative land</em>.</p> <pre><code>(defun get-neighbours (board x y) (let ((output '() )) (push (get-if-possible board (1+ x) y) output) (push (get-if-possible board (1- x) y) output) (push (get-if-possible board x (1+ y)) output) (push (get-if-possible board x (1- y)) output) (push (get-if-possible board (1+ x) (1+ y)) output) (push (get-if-possible board (1- x) (1- y)) output) (push (get-if-possible board (1+ x) (1- y)) output) (push (get-if-possible board (1- x) (1+ y)) output) output)) </code></pre> <p>You do: variable declaration, bind it to NIL, mutation of the variable, returning the variable.</p> <p>It is simply:</p> <pre><code>(defun get-neighbours (board x y) (list (get-if-possible board (1+ x) y) (get-if-possible board (1- x) y) (get-if-possible board x (1+ y)) (get-if-possible board x (1- y)) (get-if-possible board (1+ x) (1+ y)) (get-if-possible board (1- x) (1- y)) (get-if-possible board (1+ x) (1- y)) (get-if-possible board (1- x) (1+ y)))) </code></pre> <p>You can 'shorten' the code with a local macro:</p> <pre><code>(defun get-neighbours (board x y) (macrolet ((all-possible (&amp;rest x-y-combinations) `(list ,@(loop for (a b) on x-y-combinations by #'cddr collect `(get-if-posssible board ,a ,b))))) (all-possible (1+ x) y (1- x) y x (1+ y) x (1- y) (1+ x) (1+ y) (1- x) (1- y) (1+ x) (1- y) (1- x) (1+ y)))) </code></pre> <p>Now one could abstract it a bit:</p> <pre><code>(defmacro invoke-fn-on (fn &amp;rest x-y-combinations) `(funcall (function ,fn) ,@(loop for (a b) on x-y-combinations by #'cddr collect `(get-if-posssible board ,a ,b)))) (defun get-neighbours (board x y) (invoke-fn-on list (1+ x) y (1- x) y x (1+ y) x (1- y) (1+ x) (1+ y) (1- x) (1- y) (1+ x) (1- y) (1- x) (1+ y))) </code></pre> <p>About the LOOP:</p> <pre><code>&gt; (loop for (a b) on '(1 2 3 4 5 6) by #'cddr collect (list a b)) ((1 2) (3 4) (5 6)) </code></pre> <p>ON moves the pattern (a b) over the list (1 2 3 4 5 6). It would give (1 2), (2 3), (3 4), (4 5) and (5 6). With each iteration the list is moved one forward by using CDR to get the rest list. BY now says that we move by two items, by CDDR and not one item as with CDR. So we get three iterations and the pairs (1 2), (3 4) and (5 6).</p> <p>An alternative would be to slightly simplify the LOOP by introducing a different list structure for the coordinate pairs:</p> <pre><code>(defmacro invoke-fn-on (fn x-y-combinations) `(funcall (function ,fn) ,@(loop for (a b) in x-y-combinations collect `(get-if-posssible board ,a ,b)))) (defun get-neighbours (board x y) (invoke-fn-on list '(((1+ x) y ) ((1- x) y ) (x (1+ y)) (x (1- y)) ((1+ x) (1+ y)) ((1- x) (1- y)) ((1+ x) (1- y)) ((1- x) (1+ y))))) </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload