Печать содержимого массива LISP - PullRequest
3 голосов
/ 13 февраля 2012

Почему этот код не распечатывает содержимое массива -


(defun loopfn (state)
       (loop for x from 0 to 2 do
        (loop for y from 0 to 2 do
             (aref state x y))))

Здесь я передаю матрицу 3x3, которая построена следующим образом -

`(setq i (make-array '(3,3) :initial-contents '((0 1 3) (4 2 5) (7 8 6))))`

Я звоню- (loopfn i)

Edit -------- @Greg Спасибо за указание на это ... У меня был следующий вопрос .. Почему это выводит вывод ...

(defun loopfn ()
   (loop for x from 0 to 3 do
    (if (eq x 2)(return (list x)))))

Где, поскольку это печатает ноль ...

(defun loopfn ()
   (loop for x from 0 to 2 do
    (loop for y from 0 to 2 do
         (if (eq x 2)(return (list x y))))))

Я звоню

(loopfn)

Ответы [ 5 ]

2 голосов
/ 14 февраля 2012

Что касается вашего второго вопроса, (return ...) эквивалентен (return-from NIL ...), поэтому вы просто возвращаетесь из своего внутреннего LOOP во внешний. Используйте это вместо:

[11]> (defun loopfn () 
        (loop for x from 0 to 2 do 
          (loop for y from 0 to 2 do 
            (if (= x 2) (return-from loopfn (list x y))))))
[12]> (loopfn)
(2 0)

Другая возможность - собрать больше значений, чем одно, как в

[36]> (defun loopfn ()
        (loop for x from 0 to 2 nconc 
          (loop for y from 0 to 2 
                if (= y 2) 
                collect (list x y))) )
LOOPFN
[37]> (loopfn)
((0 2) (1 2) (2 2))
2 голосов
/ 13 февраля 2012

Ваш код ничего не печатает. Это также то, что вы хотите - обычно.

Но вы хотите, чтобы функции возвращали что-то полезное.

Таким образом, вы должны понимать разницу между печатью и печатью с возвратом REPL.

CL-USER > 3
3

Выше возвращается 3. Цикл Read-Eval-Print-Loop печатает возвращаемое значение.

CL-USER > (print 3)

3 
3

Над отпечатками newline, а затем в два раза больше 3. Зачем? Первый - это побочный эффект вызова PRINT, который печатает новую строку, а затем ее аргумент. Второй - это REPL, печатающий возвращаемое значение.

Обратите внимание, что EQ не для числовых сравнений. Используйте EQL вместо этого. Смотри: http://www.lispworks.com/documentation/lw50/CLHS/Body/f_eql.htm

1 голос
/ 13 февраля 2012

Ваш вызов aref получает указанный элемент, но вы ничего не делаете с ним.Вы можете прикрепить его к списку, который затем возвращается:

(defun loopfn (state)
  (let ((result '()))
    (loop for x from 0 to 2 do
     (loop for y from 0 to 2 do
          (setf result (cons (aref state x y) result))))
   result))

или вы можете просто распечатать его:

(defun loopfn (state)
  (loop for x from 0 to 2 do
       (loop for y from 0 to 2 do
        (format t "~a~%" (aref state x y)))))

Первый вариант гораздо полезнее;Вы хотите вернуть вещи, которые затем могут быть обработаны, и все, что будет передано на верхний уровень, будет распечатано для вас.

Пока вы используете LOOP, вы можете легко собрать свои значенияс COLLECT, APPEND и т. д., что является идиоматическим способом сделать это.

1 голос
/ 13 февраля 2012

Это было аккуратно рассмотрено в этой теме форума .

У внешнего цикла нет предложения, которое могло бы вызвать возвращаемое значение.

Некоторые примеры кода из этого потока:

(defun print-2d-array-as-table (array)
  (loop for i from 0 below (array-dimension array 0)
    do (loop for j from 0 below (array-dimension array 1)
             do (princ (aref array i j))
                (if (= j (1- (array-dimension array 1)))
                    (terpri)
                    (princ #\Space)))))

и один цикл:

(defun print-2d-array-as-table (array)
  (loop for i below (array-total-size array) do
    (if (zerop (mod i (array-dimension array 0)))
      (terpri)
      (princ #\Space))
    (princ (row-major-aref array i))))
0 голосов
/ 13 февраля 2012

Для вашего второго вопроса, в цикле, который не печатается, (eq x 2) никогда не соответствует действительности.Вы изменили границы цикла с 0 to 3 до 0 to 2, поэтому x никогда не достигает 2.Поскольку явное (return ...) не выполнено, функция возвращает nil.

...