我使用当前代码收到此错误:
LET: illegal variable specification
(COND (LISTP A (IF (NEGATE A) (NEGATE (REST L)) NIL))
(T (SETF A (-A) (APPEND (LIST A) (REST L)) (NEGATE (REST L)) NIL)))
我目前的代码:
(defun negate(L)
(setq x -1)
(if (not (null L))
(let ((a (fitst L))
(cond (listp a
(if (negate a)
(negate (rest L))
nil))
(t
(setf a (-a) (append (list a)(rest L))
(negate (rest L))
nil))))
)
))
以及需要传递的测试用例
o List is (1 2 3 4)
o Output should be: (-1 -2 -3 -4)
o List is (1 -2 (3 4))
o Output should be: (-1 2 (-3 -4) )
答案 0 :(得分:4)
在最礼貌的意义上,你的代码有点偏。你这周学习Lisp,不是吗?没关系!这是一种有趣的语言,可以做一些很棒的事情。
因此,我将逐步完成例行程序的制作,并带您一起参观。
您的基本情况是 -
(defun negate (n)
(if (> n 0) (- 0 n)))
(map #'negate '(1 2 3 4))
走树是更复杂的,但让我们来看看这些想法。
基本上,你有三种情况要回答:当前元素是nil,列表还是原子?
(if (not (car seq))
(if (listp (car seq))
;;Recurse
;;Otherwise negate the current element and append it to the recursed.
让我们先尝试一下:
(defun negate-seq (seq)
(if (not seq)
(return-from negate-seq))
(if (listp (car seq))
(negate-seq seq)
(list (negate (car seq)) (negate-seq (cdr seq)))))
太棒了! 除了...
(negate-seq '(1 2)) ==> (-1 (-2 NIL))
和...
(negate-seq '(1 (1 2 -3))) ==> STACK OVERFLOW!
哦,小伙子。我们现在遇到了麻烦。
首先,让我们尝试cons
而不是list
。
这清除了奇怪的嵌套列表问题。
很明显,我们已经进入了无限递归的循环。这应该是不可能的,因为我们有not seq
后卫。好的,让我们试试调试吧。我正在使用CLISP,我可以跟踪:
(trace 'negate-seq)
然后,
(negate-seq '(1 (1 2 -3)))
突然间,我看到了
的爆炸声1621. Trace: (NEGATE-SEQ '((1 2 -3)))
1622. Trace: (NEGATE-SEQ '((1 2 -3)))
1623. Trace: (NEGATE-SEQ '((1 2 -3)))
1624. Trace: (NEGATE-SEQ '((1 2 -3)))
Crikey,我忘记了我的cdr并且列出了这个名单! Hmmmm。
我们试试这个:
(defun negate-seq (seq)
(if (not seq)
(return-from negate-seq))
(if (listp (car seq))
(cons (negate-seq (car seq))
(negate-seq (cdr seq)))
(cons (negate (car seq)) (negate-seq (cdr seq)))))
回收汽车,回避汽车,将它们放在一起,我们可能会有所作为。
(negate-seq '(1 (1 2 -3))) => (-1 (-1 -2 NIL)
Hmmmm。我们来看看跟踪。
- 追踪:(NEGATE-SEQ'(1(1 2 -3)))
- 追踪:(NEGATE-SEQ'((1 2 -3)))
- 追踪:(NEGATE-SEQ'(1 2 -3))
- 追踪:(NEGATE-SEQ'(2 -3))
- 追踪:(NEGATE-SEQ'( - 3))
- 追踪:(NEGATE-SEQ'NIL)
- 追踪:NEGATE-SEQ ==> NIL
- 追踪:NEGATE-SEQ ==> (NIL)
- 追踪:NEGATE-SEQ ==> (-2 NIL)
- 追踪:NEGATE-SEQ ==> (-1 -2 NIL)
- 追踪:(NEGATE-SEQ'NIL)
- 追踪:NEGATE-SEQ ==> NIL
- 追踪:NEGATE-SEQ ==> ((-1 -2 NIL))
- 追踪:NEGATE-SEQ ==> (-1(-1 -2 NIL))
醇>
所以我递归到-3,然后......它会掉下来?奇。啊!我不断抓住事情的CDR。 CDR始终是列表。 (cdr'( - 3))是零!
让我们看看......
(大概翻找)
否定在正面回报为零。 D'哦。
(defun negate (n)
(if ( > n 0)
(- 0 n)
n))
(defun negate-seq (seq)
"Written by Paul Nathan"
(if (not seq)
(return-from negate-seq))
(if (listp (car seq))
(cons (negate-seq (car seq))
(negate-seq (cdr seq)))
(cons (negate (car seq))
(negate-seq (cdr seq)))))
答案 1 :(得分:3)
我不确定您是否正在寻找一个温和的推动来纠正所提供的代码,或者您是否正在寻求其他方式来实现它。我的第一个念头是mapcar
:
(defun negate-tree (tree)
(mapcar (lambda (e)
(cond
((null e) nil)
((listp e) (negate-tree e))
(t (- e))))
tree))
然后你可以概括出否定方面,然后编写map-tree
,接受一个函数应用于树中的原子:
(defun map-tree (f tree)
(mapcar (lambda (e)
(cond
((null e) nil)
((listp e) (map-tree f e))
(t (funcall f e))))
tree))
你可以用一元否定函数来调用它:
(map-tree #'- '(1 -2 (3 4)))
这样的调用假定树中的所有叶子都是nil
由一元否定函数容纳的。
接受nil
作为树中可能的叶子使得访问算法有点混乱,并且不清楚所提供的函数f
是否应该应用于所有叶子 - 甚至那些nil
1}} - 以便函数本身可以决定是否以及如何处理nil
。
此版本的另一个缺点是它如何处理非proper lists的cons细胞。请注意,函数listp
对于所有cons单元都返回true - 即使那些不构成正确列表的那些 - 但mapcar
确实要求其输入是正确的列表。我们可以沿着“listp
true”路径结束,递归调用mapcar
,并且mapcar
无法接收不正确的列表。这意味着上面的算法要么需要测试cons单元格,看看它们是否是正确的列表,然后再将它们交给mapcar
,也许处理那些不是叶子的那些(我不愿意说“原子”)这里记录,或者记录预期的树结构由适当的列表组成。
如果你需要接受顶级“树”,这些树不一定是列表本身,意味着一个孤立的原子是一个有效的树,或者nil
是一个有效的树,你可以撕掉它们的组成部分。在确定被检查的树是列表之后,在上面的函数中编写一个仅使用mapcar
的函数。
答案 2 :(得分:3)
如果你写:
(defun negate (n)
(if ( > n 0)
(- 0 n)
n))
然后你将你的代码限制为实数。
如果您使用Common Lisp提供的原始否定函数,它将适用于任何数字:
(mapcar (function -) '(1 2/3 #C(4 5)))
--> (-1 -2/3 #C(-4 -5))
答案 3 :(得分:0)
这就是我要做的。当然,我只考虑数字列表。因此,如果列表不是全数字,它会抛出错误。
(defun negate (list)
(flet ((negate-number (x)
(- x)))
(labels ((negate-helper (list neg-list)
(if (null list)
neg-list ; when all elements are considered return neg-list
(let ((num-or-list (car list)))
(if (numberp num-or-list)
;; if number then negate it and add it into the new list (i.e. neg-list)
(negate-helper (cdr list) (append neg-list (list (negate-number num-or-list))))
;; if list then first negate the sublist
(negate-helper (cdr list) (append neg-list (list (negate-helper num-or-list nil)))))))))
(negate-helper list nil))))
答案 4 :(得分:0)
您可以通过以下步骤实现此目的:
(defun negate (l)"returns a list of multiplication negative of elements of a list l,
element of list l to be each numbers for not to type err,
and list l may not be a list of atoms."
(cond
((null l) nil)
((consp (car l)) (cons (negate (car l))
(negate (cdr l))))
(t (cons (* -1 (car l))
(negate (cdr l))))))
还可以有另一个版本。我试图写一个尾递归程序,但它不完全是tr。
实现同样的目的,除了它没有给出与原始顺序相同的顺序。我现在无法解决这个问题:
(defun negate (l)
(negate-aux l '()))
(defun negate-aux (l A)
(cond
((null l) (reverse A));or A
((consp (car l)) (cons (negate (car l))
(negate-aux (cdr l) A)))
(t (negate-aux (cdr l) (cons (* -1 (car l)) A)))))