【问题标题】:Lisp, cons and (number . number) differenceLisp,缺点和(数字。数字)的区别
【发布时间】:2011-07-28 20:18:30
【问题描述】:

有什么区别

(cons 2  3)

'(2 . 3)

在 Lisp 中?

【问题讨论】:

  • 第二个表达式中是句号还是逗号?
  • @David:想知道是否可以更改您的答案选择。我比我更喜欢丹蕾。

标签: lisp quote cons


【解决方案1】:

它们并不完全相同,即使它们在 REPL 中评估为相同的值。考虑以下示例,其中 cons 单元被破坏性修改:

TEST> (defun literal-cons ()
        (let ((cons '(1 . 2)))
          (incf (cdr cons))
          cons))
LITERAL-CONS
TEST> (literal-cons)
(1 . 3)
TEST> (literal-cons)
(1 . 4)
TEST> (literal-cons)
(1 . 5)

与此相比:

TEST> (defun non-literal-cons ()
        (let ((cons (cons 1 2)))
          (incf (cdr cons))
          cons))
NON-LITERAL-CONS
TEST> (non-literal-cons)
(1 . 3)
TEST> (non-literal-cons)
(1 . 3)

在第一个版本中,您正在更改代码本身中的literal cons 单元格(因此,这是自修改代码)。在第二个版本中,cons 单元格不是文字的。每次调用代码时都会产生它,并且只会更改这个新的 cons 单元格。

TEST> (function-lambda-expression #'literal-cons)
(LAMBDA NIL
  (DECLARE (CCL::GLOBAL-FUNCTION-NAME LITERAL-CONS))
  (BLOCK LITERAL-CONS (LET ((CONS '(1 . 5))) (INCF (CDR CONS)) CONS))) ;; notice the '(1 . 5)
NIL
LITERAL-CONS

由于在使用破坏性操作时这可能会导致细微的错误,因此在代码中应小心使用此类文字对象。这也会影响由 cons 单元构建的列表文字('(1 2 3)(list 1 2 3))。

来自HyperSpec

字面量词。 (对象的)在程序中直接引用,而不是 不是由程序计算的;也就是说,作为数据出现在 引用形式,或者,如果对象是自评估对象,则出现 作为未引用的数据。 ``在形式 (cons "one" '("two")) 中,表达式 "one"、("two") 和 "two" 是文字对象。''

【讨论】:

  • 您的literal-cons 函数的行为必须特定于您的实现。在 SBCL 上,我得到的结果是您的 non-literal-cons。这很好奇,以至于我提出了一个新问题:stackoverflow.com/questions/20342793/…
  • @OpenLearner 对;标准未定义修改文字数据的后果。什么事情都可能发生。我认为这个答案中显示的示例很常见,但 SBCL 似乎确实在这里做了一些有趣的事情......
【解决方案2】:

两者都是具有相似结构的对象。也就是说,它们都是 cons cell,其中 2 个在 CAR 位置,3 个在 CDR 位置。

它们之间的主要区别在于 '(2 . 3) 是一个常数,而 (cons 2 3) 生成一个新的 cons 单元格。如果您采用以下两个(外观相似的)函数,则它们之间的区别应该会变得明显:

(defun a () 
  (let ((v (cons 2 3))) 
   (incf (car v))
   v)

(defun b () 
  (let ((v '(2 . 3))) 
   (incf (car v))
   v)

当您继续调用 b 时,相当多的实现会返回 '(3 . 3) '(4 . 3) 等等。

【讨论】:

    【解决方案3】:

    '(2 . 3) 是一个点对。

    (cons 2 3) 也会创建一个点对。所以这些应该评估为同一件事。

    所以一个是一个点对的文字,另一个创建一个点对。

    【讨论】:

    • 实际上有一个区别,cons 会产生一个可设置的位置,quote 会产生一个你不应该修改的常量值。
    【解决方案4】:

    (1 . 2)cons 单元格的 s 表达式语法。 cons 单元格有 1 作为car 和 2 作为cdr

    '(1 . 2) 前面带有引号字符是(quote (1 . 2)) 的缩写。 quote 指示评估者不要 (!) 评估它所包含的表单并按原样返回它。这个引用表单的值就是表单本身。 quote 说:不评价。在 Common Lisp 中,这可以被认为是常量文字数据。

    (cons 1 2) 是一个 Lisp 表单,它前面有函数 cons 和两个参数:1 和 2。如果我们评估这个表单,函数 cons 会被调用,参数是 1 和 2。cons根据定义返回一个新的 cons 单元格,其参数为 carcdr。所以 (cons 1 2) 在我们评估它时会返回一个新的 cons 单元格。

    【讨论】:

      【解决方案5】:

      它们不一样,而且是一样的。

      符号引号 (') 是一个函数,它表示:“创建此列表而不评估此列表。” 例如:'(* 2 2);它将创建列表 ( * 2 2 ) (list (* 2 2) ; 它将创建 (4) 因为列表已被评估。

      函数 cons 创建关联的对,仅此而已。 示例: (cons (a b c) (1 2 3) ) ;create (a b c . 1 2 3) (cons a (1 2 3 4) ) ;创建 (a. 1 2 3 4)

      您使用的两个函数在本例中执行相同的操作,但使用不同的方式执行此操作。 因为引号 (') 只是在 simbol 引号 (') 前面创建列表,而 cons 函数只是创建与您给函数的“itens”相关的对。

      【讨论】:

        猜你喜欢
        • 2012-08-12
        • 1970-01-01
        • 2010-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-19
        相关资源
        最近更新 更多