我想在用Lisp编写的递归函数中实现基本条件,但由于Lisp中没有return语句,我无法做到这一点。
我的Lisp代码基于此C代码
if (n==0) return;
我如何在Lisp中实现它?
答案 0 :(得分:6)
Common Lisp具有特殊形式RETURN-FROM(及其相对RETURN)来执行您想要的操作。
(defun accumulate-list (list)
(when (null list)
(return-from accumulate-list 0))
(+ (first list)
(accumulate-list (rest list))))
话虽如此,我更喜欢在编写递归函数时使用COND。
(defun accumulate-list (list)
(cond
((null list)
0)
(t
(+ (first list)
(accumulate-list (rest list))))))
答案 1 :(得分:4)
对于Algol程序员(或其中一种方言,如C,Java,perl,......) LISP中的每个表达式都像“返回表达式”。例如:
{
int x = 10;
if( x == 10 )
return 10 * 5;
else
return 5 * 19;
}
在LISP中,这可以写成:
;; direct version
(let ((x 10))
(if (= x 10)
(* 10 x)
(* 5 x)))
;; if can be anywhere
(let ((x 10))
(* x
(if (= x 10)
10
5))))
您可能会注意到LISP if
更像是三元运算符( expression ? consequent : alternative )
而非C if
。
修改强>
现在您已在C中添加了一个要转换的示例usng return
,我发现您没有使用return
返回值,而是使用goto
退出功能早。由于仅仅使用CL return-from
转到is still considered harmful并不总是正确的答案,即使这肯定是最好的字面翻译。
在任何LISP中,即使您不打算使用它,也需要提供返回值(对于其副作用调用的函数)。如果您不打算使用该值,可以使用nil
:
(if (zerop x)
nil
(something-else x))
如果您需要多个声明(针对副作用),请使用let
,progn
或将整个事项切换为cond
:
;; using let to bind as well as implicit progn
(if (zerop x)
nil
(let ((tmp (gethash x *h*)))
(setf (gethash x *h*) (+ x 1))
(something-else tmp)))
;; using progn
(if (zerop x)
nil
(progn
(setf (gethash x *h*) (+ (gethash x *h*) 1))
(something-else (gethash x *h*))))
;; using cond
(cond ((zerop x) nil)
(t
(setf (gethash x *h*) (+ (gethash x *h*) 1))
(something-else (gethash x *h*))))
答案 2 :(得分:1)
你只需要if
为整个身体,如果你真的希望返回“没有”,那么就放nil
而不是return
。
这样就可以将0到n之间的所有数字相加:
(defun somefunc (n)
(if (zerop n)
0
(+ n (somefunc (- n 1)))))
因此,如果n==0
,则递归函数返回0.否则,它会执行添加以将n
添加到f(n-1)
并返回该结果。 (请注意,这是不是理想算法,只是递归函数的一个示例。)
请记住,Lisp返回函数中最后执行的expr的值作为其值。如果n==0
,则上面返回0.如果n > 0
,则返回+
expr的结果。
如果您需要多步测试(例如,为了确保您没有传递负数),cond
就是这样(如前所述)。无论哪种方式,最后执行的事物的值是函数的值。