有人可以解释以下行为吗?具体来说,为什么函数每次都返回一个不同的列表?为什么每次调用函数时都没有some-list初始化'(0 0 0)?
(defun foo ()
  (let ((some-list '(0 0 0)))
    (incf (car some-list))
    some-list))
输出:
> (foo)
(1 0 0)
> (foo)
(2 0 0)
> (foo)
(3 0 0)
> (foo)
(4 0 0)
谢谢!
编辑:
另外,假设我希望'(1 0 0)每次输出函数,推荐的实现此函数的方法是什么?
我已经编写了下面的代码来模拟多次掷六面模具并计算每一侧落下的次数:
(defun dice (num)
  (let ((myList '(0 0 0 0 0 0)))
    (progn (format t "~a" myList)
           (loop for i from 1 to num do
                 (let ((myRand (random 6)))
                   (setf (nth myRand myList) (+ 1 (nth myRand myList)))))
           (format t "~a" myList))))
该函数在我第一次调用时效果很好,但在后续调用中,变量myList以最后一次调用结束时的值开始,而不是像我认为应该用let语句那样初始化为全零..为什么会这样?
这段经文On Lisp真的让人感到困惑 - 目前尚不清楚返回引用列表'(oh my)如何能够真正改变函数未来的行为方式:不会在函数中从头开始再次生成返回的列表,下一次是叫什么名字?
如果我们定义exclaim以使其返回值包含引用列表,
Run Code Online (Sandbox Code Playgroud)(defun exclaim (expression) (append expression ’(oh my)))然后任何后来破坏性修改返回值
Run Code Online (Sandbox Code Playgroud)(exclaim ’(lions and tigers and bears)) -> (LIONS AND TIGERS AND BEARS OH MY) (nconc * ’(goodness)) -> (LIONS AND TIGERS AND BEARS OH MY GOODNESS)可以改变函数中的列表:
Run Code Online (Sandbox Code Playgroud)(exclaim ’(fixnums and bignums and floats)) -> (FIXNUMS AND BIGNUMS AND FLOATS OH MY GOODNESS)为了对这些问题作出惊呼证据,应写成:
Run Code Online (Sandbox Code Playgroud)(defun exclaim (expression) (append expression (list ’oh ’my)))
最后一次调用exclaim将goodness结果添加到结果中的确切方式是什么?该函数没有引用任何外部变量,那么单独的调用如何nconc实际改变exclaim函数的工作方式?
下面的代码z作为局部变量,但它的行为就好像它是一个全局变量:
(defun foo (m)
  (let ((z '(stuff nil)))
    (push m (getf z 'stuff))
    (print z)))
(foo 1)
(foo 2)
(foo 3)
我希望输出是
(STUFF (1)) 
(STUFF (2)) 
(STUFF (3)) 
T
但是当我用SBCL运行它时,我明白了
(STUFF (1)) 
(STUFF (2 1)) 
(STUFF (3 2 1)) 
T
为什么会这样?这种行为是属性列表特有的吗?
首先,让我说我是Lisp的初学者.说实话,我已经有一段时间了,但是还有很多我不太了解的事情.
在我写这个问题时,我在代码中想出了一个奇怪的错误.
这是一个函数,它将返回列表(0 1 ... n)并e附加列表.它rplacd沿途使用以跟踪最后一个元素,以避免最后的调用last.
例如,(foo 4 '(x))退货(0 1 2 3 4 x).
"头"存储在a,这不是简单的nil,因为只有一个nil,而且从不复制它(如果我理解正确的话),因此我不能简单地追加nil.
(defun foo (n e)
    (let* ((a (list nil)) (tail a))
        (loop for i to n
              do (rplacd tail (setf tail (list i)))
              finally (rplacd tail (setf tail e))
              (return (cdr a)))))
(defun bar (n e)
    (let* ((a '(nil)) (tail a))
        (loop for i …我在http://www.ccs.neu.edu/home/shivers/newstyle.html网站上看到了一段代码:
> (defun element-generator ()
    (let ((state '(() . (list of elements to be generated)))) ;() sentinel.
      (let ((ans (cadr state)))       ;pick off the first element
        (rplacd state (cddr state))   ;smash the cons
        ans)))
ELEMENT-GENERATOR
> (element-generator)
LIST
> (element-generator)
OF
> (element-generator)
ELEMENTS
> (element-generator)
TO
> (element-generator)
BE
> (element-generator)
GENERATED
我不明白该功能如何记住状态.state每次函数运行时都没有重新定义到整个列表?为什么两层let(这是必要的)?如果有人能够解释这个功能是如何工作的,那将不胜感激.
编辑:解决方案是在第一个(let ...)表单中替换'(1)with(list 1).这是因为我试图修改文字数据.谢谢您的帮助!(我会放弃投票,但显然你需要15点声望......)
这是我在这个网站上的第一篇文章.
我今天解决了一些Project Euler问题,我在Common Lisp中遇到了一些意外的列表排序行为(至少对我来说):
我有一个函数,可以找到数字x的所有正确除数:
(defun divisors (x)
    "Finds all of the proper divisors of x."
    (let ((sq (sqrt x)) (divs '(1)))
        (when (integerp sq) (push sq divs))
        (loop for i from 2 to (1- (floor sq)) do
        (let ((div (/ x i)))
            (when (integerp div)
                (push i divs)
                (push div divs))))
    divs))
这个功能很棒.例如:
(divisors 100)
==> (20 5 25 4 50 2 10 1)
每当我尝试对结果列表进行排序时,就会出现问题:
(sort (divisors 100) #'<)
==> (1 2 4 5 …我一直在阅读Olin Shivers的一篇名为Stylish Lisp编程技术的文章,并发现那里的第二个例子(标有"Technique n-1")有点令人费解.它描述了一个自修改宏,如下所示:
(defun gen-counter macro (x)
       (let ((ans (cadr x)))   
     (rplaca (cdr x)       
         (+ 1 ans))
     ans))
它应该将其调用形式作为参数x(即(gen-counter <some-number>)).这样做的目的是能够做到这样的事情:
> ;this prints out the numbers from 0 to 9.
  (do ((n 0 (gen-counter 1)))
      ((= n 10) t)
    (princ n))
0.1.2.3.4.5.6.7.8.9.T
>
问题是这个带有macro函数名后面的符号的语法在Common Lisp中无效.我试图在Common Lisp中获得类似的行为是不成功的.有人可以提供CL中类似宏的工作示例吗?
SBCL 1.3.1
总之,a是一个列表,'(7),b设置为通过相同的列表setq.附加一个值b.列表c设置为追加后的预期结果,即'(7 1).a然后进行比较c并正确比较真实.但是,当a比较via时(equal a '(7 1)),它会比较false.
我的猜测是编译器没有看到追加,就像它已经完成一样b,并且已经将比较优化为常量并且结果不正确.如果是这样,有哪些选项可以提示编译器.可以a某种方式标记为特殊?或者,除了与破坏性编程相关的样式问题之外,还有其他什么东西在这里发生吗?
    (defun test-0 ()
      (let ((a '(7))
            b
            (c '(7 1)))
        (setq b a)
        (setf (cdr b) (cons 1 '()))
        (pprint (list a b c))
        (values (equal c a) (equal '(7 1) a) (equal (list 7 1) a) c a)))
    * (test-0)
    ((7 1) (7 1) (7 …我一直在调用一个破坏性的定义时接受一个奇怪的行为,接收一个局部变量作为参数,其类型是一个用引号创建的列表.
破坏性功能:
(defun insert-at-pos (pos list elem)
  (if (= pos 0)
      (cons elem list)
      (let ((aux-list (nthcdr (1- pos) list)))
        (setf (rest aux-list) (cons elem (rest aux-list)))
        list)))
错误:局部变量是使用特殊运算符引号创建的列表.
(defun test ()
 (let ((l '(1 2 3)))
   (print l)
   (insert-at-pos 2 l 4)
   (print l))) 
> (test)
(1 2 3)
(1 2 4 3)
(1 2 4 3)
> (test)
(1 2 4 3)
(1 2 4 4 3)
(1 2 4 4 …