所以我试图以递归的方式在LISP中实现一个Caesar密码,并且我已经有了基本的功能。问题是它返回一个字符列表,并且在return语句中调用concatenate'字符串只返回相同的字符列表加上一个“”。我在这里做错了什么?
(defun caesar (s n)
(if (null (concatenate 'list s))
'()
(cons
(code-char (+ n (char-code (car (concatenate 'list s)))))
(caesar (coerce (cdr (concatenate 'list s)) 'string) n)
)
)
)
答案 0 :(得分:2)
这样的正确方法是在字符串和&之间进行转换。在某种包装中列出&然后让主要功能在列表上工作。
这是一种使用CL的强大功能和优雅的方法。这样:
coerce
而不是concatenate
来更改类型,因为它就是它的用途; 首先,这里是一个使用两个方法的版本:一个包装器方法(为了方便在通用函数定义中定义),然后是执行工作的递归方法:
(defgeneric caesar (text n)
(:method ((text string) n)
;; if we're given a string just turn it into a list, then recurse
;; on the list & turn it back to a string (of the same type, hence
;; TYPE-OF).
(coerce (caesar (coerce text 'list) n) (type-of text))))
(defmethod caesar ((text list) n)
;; The recursive level (note this has various issues which are in
;; the original code & not addressed here
(if (null text)
'()
(cons (code-char (+ n (char-code (first text))))
(caesar (rest text) n))))
其次,这是一种稍微过于聪明的方法,使用特殊的终止 - { - 1}}方法。我不推荐这个,但它是CLOS可以做的事情的一个很好的演示。
null
答案 1 :(得分:0)
我很想结合输出到字符串和标签(用于递归位):
Number
0
0
6
1
0
8
0
0
0
0
10
警告:以上内容经过彻底的未经测试,只需输入此消息,因此甚至可能无法编译。它只是使建议更加混乱。