我有一个问题是对上一个主题的跟进, 我应该避免在 Prolog 中和一般情况下使用尾递归吗?
在上面链接的文章中,用户false
提供了这个代码示例和这个解释......
早在 1970 年代,主要的 AI 语言是 LISP。相应的定义将是......
(defun addone (xs) (cond ((null xs) nil) (t (cons (+ 1 (car xs)) (addone (cdr xs))))))
...不是直接尾递归的:原因是
cons
:在那个时候的实现中,它的参数首先被评估,然后才cons
可以执行。因此,按照您的指示重写(并反转结果列表)是一种可能的优化技术。然而,在 Prolog 中,您可以
cons
在知道实际值之前创建先验,这要归功于逻辑变量。这么多在 LISP 中不是尾递归的程序,在 Prolog 中被翻译成尾递归程序。在许多 Prolog 教科书中仍然可以找到这种影响。
我的问题是:上述 LISP 代码的好的 Prolog 翻译是什么?
编辑:添加了运行中的 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 功能的文档
缺点对象 1 对象 2 => 缺点
创建一个新的 cons ,其 car 为 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 是一个 cons , car 返回那个 cons 的 car。如果 x 为 nil ,则 car 返回 nil 。
(cdr x) => 对象
如果 x 是 cons ,则 cdr 返回该 cons 的 cdr。如果 x 为 nil ,则 cdr 返回 nil 。
cond {条款}* => 结果*
子句::= (测试形式*)测试表单按照它们在参数列表中给出的顺序一次评估一个,直到找到一个评估为 true 的测试表单。
如果该子句中没有表单,则 cond 表单返回 test-form 的主值 [ed: test-form 的第一个值,如果没有值,则返回 nil]。否则,与此测试表单关联的表单将按从左到右的顺序作为隐式 progn 进行评估,最后一个表单返回的值由 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