(defun take-n (lst i)
(setf newlst '())
(dotimes (n i)
(setf newlst (cons (car lst) newlst))
(print (cons (car lst) newlst))
(setf lst (cdr lst)))
(return newlst))
(print (take-n '(1 2 3) 2))
这给我一个RETURN-FROM错误:当前看不到名为NIL的块。我已经尝试过将return语句移走,但是我不确定它的含义。
答案 0 :(得分:7)
请以Lisp方式缩进代码(可以在许多编辑器(例如Emacs)中自动完成):
(defun take-n (lst i)
(setf newlst '())
(dotimes (n i)
(setf newlst (cons (car lst) newlst))
(print (cons (car lst) newlst))
(setf lst (cdr lst)))
(return newlst))
(print (take-n '(1 2 3) 2))
不要setf
事先未声明的变量:(setf newlst '())
指的是假设的全局变量newlst
,但是在函数中,您应该努力只具有局部变量州。您可以使用let
在块中引入变量,如下所示:
(let ((new-list ()))
...
;; here you can setf new-list if you need
...)
(setf newlst (cons (car lst) newlst))
也可以写成(push (car lst) newlst)
,但是请不要使用过分缩写的名称。例如,您可以使用list
和new-list
。
return
返回到名为nil
的封闭块,但是这里没有这样的块。相反,defun
引入了一个隐式块,其名称类似于您定义的函数,即您隐式地:
(block take-n
...)
因此,如果您想从中返回,则需要执行(return-from take-n newlst)
。
但是,您不需要返回,因为该函数中最后一个要求值的形式仍然是与该函数调用关联的值。
答案 1 :(得分:5)
您不需要使用RETURN
。在Lisp中,函数主体中的最后一个表达式是自动返回的,因此只需将变量放在函数的末尾即可。另外,您应将本地变量与LET
绑定,而不要分配全局变量。
(defun take-n (lst i)
(let ((newlist '()))
(dotimes (n i)
(setf newlst (cons (car lst) newlst))
(print (cons (car lst) newlst))
(setf lst (cdr lst)))
newlst))
您得到的错误是因为DEFUN
在函数体周围放置了一个命名块,因此您需要使用(return-from take-n newlst)
。 return
仅可用于从未命名的块(名称为NIL
的块)返回;这些会自动放在DO
之类的循环宏周围。