你想知道它是与偏好的差异:
(defun f (x)
(let* ((x 4) (y (1+ x)))
(flet ((g (x) (+ 2 x)))
(g y))))
和
(defun f (x)
(flet ((g (x) (+ 2 x)))
(let* ((x 4) (y (1+ x)))
(g y))))
?
在这种情况下,您放置哪个订单flet
/labels
和let
/let*
确实无关紧要。它会产生相同的结果,您的CL实现可能会优化您的代码,使得结果无论如何都是相同的。
在一个LISP-1中,你会把它放在同一个let
,然后问题是如果你应该把lambda首先或最后。似乎喜欢我的味道。
唯一不同的情况是当你在你的函数中进行自由变量计算时。像这样:
(defun f (x)
(let ((y (1+ x)))
(flet ((g (x) (+ 2 x y))) ; y is free, made in the let*
(g x))))
(f 5) ; ==> 13
由于函数使用自由变量,所以切换顺序现在不可能移动逻辑。你可以把let
的g
这样的定义中:
(defun f (x)
(flet ((g (z) ; renamed to not shadow original x
(let* ((y (1+ x)))
(+ 2 z y)))
(g x))))
但是想象一下,你mapcar
,reduce
或递归使用它。然后它会在每次迭代中完成计算,而不是在调用之前进行一次计算。这些真的很重要。
你有一些括号错误;也没有使用函数参数'x'。 – uselpa
我想,既然你说过“习惯用法”,可以通过调查现有代码,并查看这种情况发生的频率,来客观地回答这个问题,但即使如此,你也必须决定哪些代码是惯用的,哪些不是。因此,我认为这可能有点过于主观。也就是说,在flet内部没有任何问题,或者让flet进入内部。如果你想模仿Haskell结构,我不会为编写惯用代码而担心,尽管如此;只是担心与自己的代码一致。 –
-----是的。 ----- –