LET block 内的嵌套 FLET block (反之亦然)

标签 nested lisp let

LET block 嵌套在 FLET/LABELS block 中是惯用的还是非惯用的?

同样,我可能完全错了,但我正在尝试模仿 Haskell 中的通用 where block (所以我有一个 defun 并且我想要编写对值和函数使用某些临时绑定(bind)的代码。

如果这些不是惯用语(毕竟,我不应该期望将用法从一种语言转移到另一种语言),那么正确的方法是什么?

例如类似的东西(下面是愚蠢的例子......)

(defun f (x) (
  (let* ((x 4)
         (y (1+ x))
         (flet ((g (x) (+ 2 x)))
            (g y))))

最佳答案

您想知道这是否是偏好差异:

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

但假设您将它与 mapcarreduce 或递归一起使用。然后它会为每次迭代完成计算,而不是在调用之前计算一次。这些是真正重要的案例。

关于LET block 内的嵌套 FLET block (反之亦然),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23601988/

相关文章:

lisp - 需要了解带递归的 LISP 程序

recursion - 在 F# 中定义递归函数内部函数与外部函数的性能副作用是什么?

templates - Go:如何管理嵌套模板?

c - 嵌套for循环,运行系列10000次

nested - nanoc 支持嵌套部分吗?

java - 如何在 LISP 解释器中实现闭包

lisp - 整数lisp的最小值

javascript - For loop let scope stackblitz vs chrome 开发工具

javascript - 我对 for 循环中的 javascript let 和 var 感到困惑?

C# Linq 到 xml。嵌套在父对象中的项目