【问题标题】:Lambda function for optimization in LispLisp 中用于优化的 Lambda 函数
【发布时间】:2021-01-08 16:06:31
【问题描述】:

考虑以下 Lisp 中的函数定义:

(defun f (l)
    (cond
        ((null l) 0)
        ((> (f (car l)) 2) (+ (car l) (f (cdr l))))
        (T (f (car l)))
    )
)

给出一个避免双重递归调用(f (car l))的解决方案。您不会使用 set、setq、setf。证明答案。

我是这样处理的:

(defun f2 (l)
    (cond
        ((null l) 0)
        ((lambda (x) 
           (cond
                ((> x 2) (+ (car l) (f2 (cdr l))))
                (T x)
           )
         ) (f2 (car l)) 
        )
    )
)

我想听听一些意见。顺便说一句,这只是一个练习。这个函数不应该做一些连贯的事情。

【问题讨论】:

  • 如果您更仔细地格式化您的代码,这将对包括您自己在内的所有人有所帮助。惯用的 Lisp 看起来与您所拥有的完全不同,这是有充分理由的。首先停止括号在多行上的分散;括号不是分号,Lisp 也不是 C。现在,当您尝试验证 ff2 具有相同的行为时,f2 是否编译过?
  • 它不会编译,而是一个练习。我放了括号是为了看看事情从哪里开始和结束,我觉得它更具可读性。
  • "它不编译,而是一个练习。"练习是关于生成正确的代码,想一想,编译器可以帮助你做到这一点
  • @hackermanwasd -- f 编译,但 f2 不编译:这暗示有问题,转换不成功。

标签: lambda lisp common-lisp


【解决方案1】:

在这里,我尝试以 Lisp 方式重新格式化您的代码:

(defun f2 (l)
  (cond
    ((null l) 0)
    ((lambda (x)
       (> x 2)
       (+ (car l) (f (cdr l)))
       (T (f (car l))))
     (f (car l)))))

使用lambda 可以计算一次值并将其绑定到变量,实际上您可以将cond 的最后两个原始情况合并到lambda 中。

但是,有多个问题导致代码不正确。

  • 递归调用应该调用f2,而不是f
  • 你不能在lambda 中移动cond 的测试子句,这不是Lisp 语法的工作方式。您可能只需要一个 if,但如果在 (> x 2) 案例的 lambda 中错过了一个 cond
  • lambda 内,不要调用(f2 (car l)),因为使用中间函数的全部意图是使用参数x(这是关于(T (f (car l))) 形式,它看起来像一个cond 子句但被解释作为函数调用)

【讨论】:

  • 为什么不到处都是 f2?所以你不要并行使用 2 个函数
  • 我做了一个重构以在任何地方使用 f2
  • 现在不行了吗?
  • 不,您的 cond 格式不正确,请尝试使用 lisp 解释器运行代码,例如 sbcl(steel bank common lisp)、ecl(embedded common lisp)甚至是 emacs,因为子集您正在使用的代码也可以作为 emacs-lisp 使用
  • 已编辑,希望现在很好。通常我在 Visual Studio Code 中编写 Common Lisp 并在命令行中使用“clisp program.lisp”运行它。没用过其他的IDE,以后可能会尝试其他的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-18
  • 1970-01-01
  • 2012-11-17
  • 2022-01-08
  • 2020-01-27
  • 1970-01-01
  • 2021-02-13
相关资源
最近更新 更多