在通用LISP中递归连接字符列表

时间:2017-04-16 13:24:40

标签: recursion encryption lisp concatenation common-lisp

所以我试图以递归的方式在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)
        )
    )
)

2 个答案:

答案 0 :(得分:2)

这样的正确方法是在字符串和&之间进行转换。在某种包装中列出&然后让主要功能在列表上工作。

这是一种使用CL的强大功能和优雅的方法。这样:

  • 使用CLOS方法进行包装 - 这可能会使它没有资格作为家庭作业提交,以防它就是这样,但是很好地证明了我认为CLOS有多漂亮,也是我的意思实际上写这样的东西;
  • 在包装器方法中使用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

警告:以上内容经过彻底的未经测试,只需输入此消息,因此甚至可能无法编译。它只是使建议更加混乱。