【发布时间】:2017-10-09 19:16:33
【问题描述】:
我有一个问题是上一个主题的后续问题, Should I avoid tail recursion in Prolog and in general?
在上面链接的文章中,用户false
提供了这个代码示例和这个解释......
早在 1970 年代,主要的 AI 语言是 LISP。和 相应的定义应该是...
(defun addone (xs) (cond ((null xs) nil) (t (cons (+ 1 (car xs)) (addone (cdr xs))))))...不是直接尾递归的:原因是
cons: 在那个时候的实现中,它的论点首先被评估, 只有这样,cons才能被执行。所以像你一样重写这个 指示(并反转结果列表)是可能的 优化技术。然而,在 Prolog 中,您可以在知道之前创建
cons实际值,这要归功于 逻辑变量。这么多节目 在 LISP 中不是尾递归的,在 LISP 中被翻译成尾递归程序 序言。这种影响仍然可以在许多 Prolog 中找到 教科书。
我的问题是:上面的 Prolog 翻译什么是好的 LISP 代码?
编辑: 添加了 lisp 代码示例和 lisp 文档描述了各种 lisp 函数。
插件实例
1 > (addone '(1 2 3))
(2 3 4)
2 > (addone '('()))
> Error: The value 'NIL is not of the expected type NUMBER.
> While executing: CCL::+-2, in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
> Type :? for other options.
3 > (addone '(a b c))
> Error: The value A is not of the expected type NUMBER.
> While executing: CCL::+-2, in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
> Type :? for other options.
3 > ^C
lisp 功能文档
cons object-1 object-2 => 缺点
创造一个新的缺点, 其汽车是 object-1 , 其 cdr 为 object-2 。
例子 (cons 1 2) => (1 . 2)
(cons 1 nil) => (1)
(cons nil 2) => (NIL . 2)
(cons nil nil) => (NIL)
(cons 1 (cons 2 (cons 3 (cons 4 nil)))) => (1 2 3 4)
(cons 'a 'b) => (A . B)
(cons 'a (cons 'b (cons 'c '()))) => (A B C)
(cons 'a '(b c d)) => (A B C D)
(汽车 x) => 对象
如果 x 是一个缺点, 车返回那个缺点的车。 如果 x 为 nil , 汽车返回零。
(cdr x) => 对象
如果 x 是一个缺点, cdr 返回该 cons 的 cdr。 如果 x 为 nil , cdr 返回零 .
cond {clause}* => 结果*
子句::= (测试形式*)测试表单按照它们的顺序一次评估一个 在参数列表中给出,直到找到一个测试形式 计算结果为真。
如果该子句中没有形式,则 test-form [ed: test-form 的第一个值,如果有,则为 nil are no values] 由 cond 形式返回。否则,表格 与此测试表格相关联的按顺序评估,留给 对,作为隐式预测,以及最后一个返回的值 表单由 cond 表单返回。
一旦一个测试表单产生真值,就不会再有其他测试表单 评估。如果没有测试表单返回 true,则返回 nil
看 http://www.lispworks.com/documentation/HyperSpec/Body/m_cond.htm#cond 了解更多信息。
defun 函数名 lambda-list 形式* => 函数名
看 http://www.lispworks.com/documentation/HyperSpec/Body/m_defun.htm#defun 了解更多信息。
t => T
t => T
(eq t 't) => T
(case 'b (a 1) (t 2)) => 2
【问题讨论】:
-
你知道 Lisp 程序是做什么的吗?
-
为什么要在问题中记录 Lisp 功能?任何希望回答问题的人都应该知道基本功能或知道在哪里可以找到任何详细信息。你不应该用大量基本的 Lisp 语言文档来混淆你的问题。
-
我完全不同意。你能不能把提供这样的参考视为一项很好的服务?特别是当问题是关于从外语语法(lisp)到“本地”观众的语法(序言)的翻译时。如果是“请帮我把这个法语翻译这个法语成英语”的问题——提供 5 个最重要单词的定义作为起点是否不合适?
-
问题确实要求翻译 - 翻译可以解释,但肯定不能(仅)解释“提供一些序言提供此功能,请忽略原始语法、语义、单词选择和方法,随你喜欢”。使用这种方法的答案没有错,但还有其他可能性。
-
“翻译”在解释上可能会有一些差异,但主要的是:功能相同,结构相同或相似,这是我原来的答案提供的.事实上,我故意避免使用 CLP(FD) 方法(这是我通常会选择的方法),因为您正在寻找与 Lisp 代码等效的东西。我确实用 CLP(FD) 更新了答案。
标签: prolog common-lisp tail-recursion code-translation tailrecursion-modulo-cons