【问题标题】:Common Lisp: cons inside loopCommon Lisp:循环内的缺点
【发布时间】:2009-11-07 10:32:13
【问题描述】:

我想知道为什么在下面的代码中,d 没有被cons 编入x。 任何提示都非常感谢。

(defun it (x) 
  (setq f '(a b c))
  (dolist (d f)
    (cons d x))
  (print x))

谢谢!

【问题讨论】:

  • 您必须先让我们更好地了解该功能应该做什么,然后我们才能为您提供更好的提示。
  • 我希望将列表 f 的每个元素都添加到列表 x 中
  • 请注意,F 没有在任何地方定义。这很糟糕。

标签: lisp common-lisp


【解决方案1】:

我对 LISP 了解不多,但我认为我知道以下几点可能会对您有所帮助:

  • (cons d x) 没有将 d “放入” x;它创建了一个新值,该值由 d 和 x 的内容组成。如果 x 是一个列表,那么 (cons d x) 也将是一个列表。

  • (cons d x) 不会改变任何东西;它创造了一个价值,但如果你没有捕捉到这个价值,它就会再次被丢弃。特别是,该表达式不会改变 x。

【讨论】:

  • cons 不会创建新列表。它只是创建一个新的 cons 单元格(一个具有两个指针的结构并返回它。该单元格的 CAR 是 CONS 的第一个参数,该单元格的 CDR 是 CONS 的第二个参数。
  • 我知道,但我希望保持简单。不过,你说得对,我不应该让谎言站在那里。我会编辑我的帖子。
【解决方案2】:

您需要使用 PUSH 破坏性地更新变量。 CONS 只是返回一个新的 cons 单元格。如果你不对那个 cons 单元做任何事情,那么它就消失了。也不是您需要声明所有变量。 LET 引入了一个新的局部变量 F,因此 LET 在您的示例中很有用。仅仅对未声明的变量执行 SETQ 或 SETF 并不是一件好事——实际上在 Lisp 标准中,这种操作的结果是未定义的。

(defun it (x) 
  (let ((f '(a b c)))
    (dolist (d f)
      (push d x))
    (print x)))

或者使用更实用的方法。

(defun it (x)
  (print (append '(a b c) x)))

您可能还想调用 REVERSE 以获取列表元素的不同顺序。

【讨论】:

    【解决方案3】:

    如果我正确理解您的意图,您希望将包含符号 abc 的列表 f 添加到提供的参数x。这个怎么样?

     (defun it (x)
       (append (if (listp x)
                   x
                   (list x))
               '(a b c)))
    

    请注意,cons 不会修改任何现有结构;它的意思是“构造”,它创建了新结构。在这种情况下,您不需要修改任何内容,除非您故意尝试编写一个 destructive 函数 来修改参数 x 所指向的对象。此类函数很少见,通常以警告此类破坏性行为的方式命名,例如nconcnreverse。前导 n 的意思是“non-consing”,暗示它修改了现有的结构,而不是创造新的结构。

    【讨论】:

      猜你喜欢
      • 2013-05-16
      • 1970-01-01
      • 2021-09-12
      • 1970-01-01
      • 2016-08-09
      • 2018-09-23
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      相关资源
      最近更新 更多