打印LISP数组内容

3
为什么这段代码不能打印出数组的内容 -
在这里,我传入了一个3x3的矩阵,它是这样构建的 -
我调用 - (loopfn i)
编辑-------- @Greg 感谢您指出这个问题... 我有以下问题.. 为什么会打印输出...
(defun loopfn ()
   (loop for x from 0 to 3 do
    (if (eq x 2)(return (list x)))))

而这个打印出来是 nil...

(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)

1
你忘记了实际打印输出的部分吗?比如 (print (aref ...)) - Greg Hewgill
@Greg Hewgill 你能否请帮我澄清一下我的问题的第二部分...我已经编辑过了... - Fox
EQ不适用于数字比较。请使用EQL或=。 - Rainer Joswig
嗨!你知道吗?如果任何答案回答了你的问题,你可以通过点击其旁边的空心绿色勾号来接受该答案。这将提高你的声誉。 :) - Will Ness
5个回答

2

您的代码没有打印任何内容。通常情况下,这也是您想要的。

但您希望函数返回一些有用的东西。

因此,您需要理解打印和REPL打印返回值之间的区别。

CL-USER > 3
3

上面的代码返回3。读取-求值-打印循环会打印返回值。
CL-USER > (print 3)

3 
3

上面的代码会先打印一个换行符,然后输出两次数字 3。为什么呢? 第一个是 PRINT 调用的副作用,它会先打印换行符,再打印它的参数。 第二个是 REPL 打印返回值。 请注意,EQ 不适用于数值比较,请使用 EQL 代替。 详见:http://www.lispworks.com/documentation/lw50/CLHS/Body/f_eql.htm

2
关于你的第二个问题,(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))

1

这个问题在论坛话题中已经很好地解决了。

外层循环没有任何子句会导致返回值。

以下是该主题中的一些代码示例:

(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))))

嗨,感谢提供链接……我修改了我的代码……(defun loopfn (state target) (loop for x from 0 to 2 do (loop for y from 0 to 2
do (if (eq (aref state x y) target) (princ (list x y))))))但输出结果是(2 1 ) Nil ……我的问题是如何只输出列表(2 1),而不是nil……
- Fox
默认情况下,必须返回某些内容,即使只是 nil,但是如果调用 (values),则根本不会返回任何内容。 - John Pick

1

你调用了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,就可以轻松地使用COLLECTAPPEND等方法收集您的值,这是惯用的方法。


嗨,感谢提供的信息……我修改了我的代码……(defun loopfn (state target) (loop for x from 0 to 2 do (loop for y from 0 to 2
do (if (eq (aref state x y) target) (princ (list x y))))))但输出结果是(2 1 ) Nil ……我的问题是如何只输出列表(2 1),而不是nil……
- Fox

0
关于您的第二个问题,在不打印的循环中,(eq x 2) 从未为真。您已将循环边界从 0 到 3 修改为 0 到 2,因此 x 永远不会达到 2。由于没有显式执行 (return ...),所以函数返回 nil

1
这里的“0 to 2”是指从0到2,而不是从0到小于2。你可以尝试使用(loop for x from 0 to 2 collect x)命令,并查看循环中X所取得的值。 - Vatine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接