在你做任何其他事情之前,请先看看可用的介绍性lisp文本。
[dons code-review hat]
(defun prefix (a y) (cond ((null y) nil)
(t (cons (cons a (car y)) (prefix a (cdr y))))))
(setq result prefix(a (cons 1 2)))
(print result)
首先,这些定义并没有按照您的散文描述所说的那样做;作为递归函数的一部分,您没有任何打印。您 print result
,但那是在prefix
ed 列表全部放在一起之后。您的prefix
函数也不会返回新符号,而是返回对。
无需设置中间值即可打印它们;Lisp 函数隐式返回,并且可以在没有的情况下组合setq
(defun prefix (a y)
(cond ((null y) nil)
(t (cons (cons a (car y))
(prefix a (cdr y))))))
(print prefix(a (cons 1 2)))
Lisp 完全用前缀表示,函数名出现在调用括号内。
...
(print (prefix a (cons 1 2)))
a
在您的prefix
通话中是一个未绑定的变量。我认为您要么打算使用“符号a
”,即'a
,要么使用“关键字a
”,即:a
. 如果您只是通过a
,Lisp 将尝试将该名称评估为变量,如果您没有为其分配值,则会失败。
...
(print (prefix 'a (cons 1 2)))
您的第二个论点prefix
不是正确的列表;这是一对。为了看到区别,您需要查看两种构造的底层指针结构。
(cons 1 2) => [ 1 | 2 ]
(list 1 2) => [ 1 | ]
\
[ 2 | ]
\
NIL
如果您尝试在函数期望正确列表的情况下使用对,则会收到错误#<TYPE-ERROR expected-type: LIST datum: 2>
,因为对的尾部不是列表,而 a 的尾部list
是.
(defun prefix (a y)
(cond ((null y) nil)
(t (cons (cons a (car y))
(prefix a (cdr y))))))
(print (prefix 'a (list 1 2)))
至此,您已经有了一个可运行的程序。(print (prefix 'a (list 1 2)))
在定义该函数后在 REPL 进行评估应该会给你
CL-USER> (print (prefix 'a (list 1 2)))
((A . 1) (A . 2))
((A . 1) (A . 2))
请注意,我们有重复的输出;这是因为 Lisp REPL 会自动打印您评估的任何表单的返回值,这意味着您实际上可以print
完全删除。
CL-USER> (prefix 'a (list 1 2))
((A . 1) (A . 2))
为了执行您所说的操作(以第一个参数为前缀创建一个新的符号列表),您实际上需要使用一些字符串操作并intern
创建符号。
(defun prefix (a y)
(cond ((null y) nil)
(t (cons (intern (format nil "~a~a" a (car y)))
(prefix a (cdr y))))))
(prefix 'a (list 1 2))
现在应该返回(A1 A2)
。请注意,Common Lisp 不区分大小写,会自动将小写符号转换为大写。
递归是一个很好的学习工具,尾递归是 Scheme 中的主要迭代结构,但如果可以的话,迭代地做事通常是个好主意。请注意,CL 不保证尾调用优化,因此这通常意味着使用loop
或mapcar
(或dolist
在某些情况下)。
(defun iterative-prefix (a a-list)
(loop for elem in a-list
collect (intern (format nil "~a~a" a elem))))
(defun map-prefix (a a-list)
(mapcar
(lambda (elem) (intern (format nil "~a~a" a elem)))
a-list))
这些都将为您提供与递归版本相同的输出,但如果您为它们提供足够长的列表,则不会有耗尽堆栈空间的风险。
CL-USER> (prefix 'a (make-list 100000 :initial-element 1))
Control stack guard page temporarily disabled: proceed with caution
Control stack guard page temporarily disabled: proceed with caution
; Evaluation aborted on #<SB-KERNEL::CONTROL-STACK-EXHAUSTED {1004D674F3}>.
CL-USER> (iterative-prefix 'a (make-list 100000 :initial-element 1))
(A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 ...)
CL-USER>