(Common lisp) 扁平化和传递列表
(Common lisp) Flattening and passing list
我在这里要做的是首先展平任何给定的列表,然后将该列表传递到我的加密函数中。虽然这不起作用,但我不确定为什么。
这是我目前所拥有的,
(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))
我应该在 "encrypt" 函数中调用 "flatten" 函数吗?或者在递归调用之后在 "flatten" 函数中调用 "encrypt"?
我将如何正确传递扁平化列表?
FLATTEN
不会破坏性地修改列表。它创建一个包含扁平化内容的新列表。您必须使用它的 return 值而不是原来的 ENCTEXT
。这很容易通过调用 ENCRYPT
来实现:
(encrypt (flatten '((A) (B))))
并从 ENCRYPT
中删除对 FLATTEN
的调用。这是您的代码的更简洁版本:
(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))))
我在这里要做的是首先展平任何给定的列表,然后将该列表传递到我的加密函数中。虽然这不起作用,但我不确定为什么。 这是我目前所拥有的,
(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))
我应该在 "encrypt" 函数中调用 "flatten" 函数吗?或者在递归调用之后在 "flatten" 函数中调用 "encrypt"? 我将如何正确传递扁平化列表?
FLATTEN
不会破坏性地修改列表。它创建一个包含扁平化内容的新列表。您必须使用它的 return 值而不是原来的 ENCTEXT
。这很容易通过调用 ENCRYPT
来实现:
(encrypt (flatten '((A) (B))))
并从 ENCRYPT
中删除对 FLATTEN
的调用。这是您的代码的更简洁版本:
(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))))