2016-05-01 121 views
0

我在这里要做的是首先弄平任何给定的列表,然后将该列表传递给我的加密函数。虽然这不起作用,我不知道为什么。 这里是我到目前为止,(通常lisp)展平和通过名单

(defun flatten (l) 
    (cond ((null l) l) 
     ((atom l) (list l)) 
     (t (loop for a in l appending (flatten a)))) 

) 



(defun encrypt(enctext) 
(flatten enctext) 

    (if(eq 'A (first enctext)) ;If the first charcater equals 'A'... 
     (progn     ;To allow multiple statements in an if statement 
     (prinC#\B)    ; First statement, print this character 
     (encrypt(rest enctext)))) ;Second statement, run function again passing the rest of the characters 

    (if(eq 'B (first enctext)) 
     (progn 
     (prinC#\C) 
     (encrypt(rest enctext)))) 


) 

这是如何我调用加密功能

(encrypt '((A)(B)) 

我应该叫我“加密”功能的“扁平化”的功能?或者在递归调用之后在“扁平化”函数中调用“加密”? 我该如何正确地通过展平名单?

回答

1

FLATTEN不破坏性地修改列表。它会创建一个包含展平内容的新列表。你必须使用它的返回值而不是原来的ENCTEXT。这是很容易通过调用ENCRYPT实现,如:

(encrypt (flatten '((A) (B)))) 

和删除ENCRYPTFLATTEN呼叫。这是你的代码的有些清洁版本:

(defun encrypt (enctext) 
    (unless (endp enctext) 
    (princ (ecase (first enctext) ; I'm assuming the input shouldn't 
      (A #\B)    ; contain any symbols that aren't 
      (B #\C)))   ; handled here. Otherwise use CASE 
    (encrypt (rest enctext)))) ; instead of ECASE. 

如果你想这样做,没有一个单独的函数调用拼合列表中,你需要递归下降到里面ENCRYPT输入列表中。喜欢的东西:

(defun encrypt (enctext) 
    (unless (endp enctext) 
    (let ((first (first enctext))) 
     (if (atom first) 
      (princ (ecase first 
        (A #\B) 
        (B #\C))) 
      (encrypt first))) 
    (encrypt (rest enctext)))) 

(encrypt '((A) (B))) 
; BC 

当然,如果你没有理由要做到这一点使用递归的深度和广度,循环会使代码更加清晰:

(defun encrypt (enctext) 
    (dolist (el enctext) 
    (if (atom el) 
     (princ (ecase el 
       (A #\B) 
       (B #\C))) 
     (encrypt el)))) 
+0

谢谢!我试图将一切都纳入一个功能,但我甚至不知道你是否可以做到这一点。 – Jcan1995

+0

@JoshuaCantero我添加了另一个例子,它不会变扁。 – jkiiski

+0

是的,我注意到,它有很大的帮助。 – Jcan1995