【问题标题】:Explain me my LISP code解释一下我的 LISP 代码
【发布时间】:2016-07-20 13:44:39
【问题描述】:

我是 LISP 的新手,我正在尝试理解递归。

我知道递归需要一个 STOP 条件。在下面的代码中,您能否向我解释为什么(equal x 0) 1 是我的停止条件,因为fact(- X 1) 可以像我的第二种情况一样无限期地继续,我已将t 设置为cond 的第二行,这意味着它应该继续。

但是当我运行程序时,它运行良好。下面是我的代码(偶然发现)

(defun fact(x)
    (cond
        ((equal x 0) 1)
        (t (*(fact(- x 1)) x)) 
    )
)

【问题讨论】:

  • 如果你传递一个负数,我可以无限期地继续。
  • consequent 或 Alternative 的结果是 if 的值,最后一个表达式是返回值。在 JS 中会是这样的:function fact(x) { return x === 0 ? 1 : x * fact(x-1);}

标签: lisp


【解决方案1】:

cond 表达式有许多子句。每个子句的格式为(expr1 expr2)。如果expr1 评估为真,则expr2 is evaluated and that is the returned value of thecond`。不评估其他子句。

因此,一旦 x 变为 0cond 的第一个子句的计算结果为 true,并且对 fact 的调用返回 1

cond 的另一个子句具有t 的第一个表达式,根据定义它是正确的;因此,如果不使用第一个子句,它总是使用第二个子句。 (带有tcond 子句就像其他语言中“if”语句中的“else”。)

这个函数是递归的,如果你用参数 2 调用它,它会检查 2 == 0,如果不是这样,它会将 2 与递归调用自身返回的值乘以 1。因为 1 != 0 它将返回 1 的值乘以用 0 递归调用自身的值。由于 0 确实等于 0 它只返回 1,它用于一层返回 1,然后在此递归的顶层使用返回2.

Common Lisp 有一个函数trace,它可以让您查看函数何时被调用以及使用哪些参数。通常,每个递归调用都会缩进,因此您可以看到如下内容:

(fact 2)
    (fact 1)
       (fact 0)

这有助于理解这个函数。

(正如评论中提到的 - 此函数无法捕获负输入的情况 - 但这是错误处理,可以轻松修复)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    相关资源
    最近更新 更多