我在这里尝试做的是先将任何给定列表展平,然后将该列表传递给我的加密函数。虽然这不起作用,但我不确定为什么。 这是我到目前为止所拥有的,
(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))
我应该在“加密”功能中调用“展平”功能吗?或者在递归调用后在“flatten”函数中调用“encrypt”? 我将如何正确地通过扁平列表?
答案 0 :(得分:1)
FLATTEN
不会破坏性地修改列表。它会创建一个包含展平内容的新列表。您必须使用其返回值而不是原始ENCTEXT
。这可以通过调用ENCRYPT
来轻松实现:
(encrypt (flatten '((A) (B))))
从FLATTEN
移除对ENCRYPT
的来电。这是一个更简洁的代码版本:
(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))))