Лисп, минусы и (число. число) разница

В чем разница между

(cons 2  3)

а также

'(2 . 3)

в лиспе?


person David Degea    schedule 28.07.2011    source источник
comment
Это точка или запятая во втором выражении?   -  person Evan Mulawski    schedule 29.07.2011
comment
@David: интересно, можно ли изменить выбор ответа. Дэнлей мне нравится больше, чем мой.   -  person    schedule 29.07.2011


Ответы (5)


'(2 . 3) — пара точек.

(cons 2 3) также создает точечную пару. Таким образом, они должны оценивать одно и то же.

Таким образом, один является литералом для точечной пары, другой создает точечную пару.

person Community    schedule 28.07.2011
comment
На самом деле есть разница в том, что cons создаст устанавливаемое место, а quote создаст постоянное значение, которое вы не должны изменять. - person thodg; 16.06.2017

Они не совсем одинаковы, даже несмотря на то, что они оцениваются в одни и те же значения в 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)

В первой версии вы меняете литерал 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

Поскольку это может привести к тонким ошибкам при использовании деструктивных операций, следует быть осторожным с такими литеральными объектами в коде. Это также влияет на литералы списка ('(1 2 3) против (list 1 2 3)), которые строятся из cons-ячеек.

Из HyperSpec:

буквальный прил. (объекта), на который ссылаются непосредственно в программе, а не на вычисляемый программой; то есть, отображаемые как данные в форме кавычек, или, если объект является самооценивающимся объектом, отображаемые как данные без кавычек. ``В форме (cons "один" '("два")) выражения "один", ("два") и "два" являются литеральными объектами.''

person danlei    schedule 28.07.2011
comment
Поведение вашей функции literal-cons должно соответствовать вашей реализации. На SBCL я получаю результаты как ваш non-literal-cons. Это достаточно любопытно, поэтому я открыл новый вопрос об этом: stackoverflow.com/questions/20342793/ - person johnbakers; 03.12.2013
comment
@OpenLearner Право; последствия изменения литеральных данных стандартом не определены. Может произойти все, что угодно. Я думаю, что пример, показанный в этом ответе, является обычным, но SBCL, похоже, делает здесь что-то интересное… - person Joshua Taylor; 03.12.2013

Оба являются объектами с похожей структурой. То есть обе они являются cons-клетками, 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)

Довольно много реализаций вернут '(3 . 3) '(4 . 3) и так далее, пока вы продолжаете вызывать b.

person Vatine    schedule 29.07.2011

(1 . 2) — это синтаксис s-выражения для ячейки cons. Ячейка cons имеет 1 как car и 2 как cdr.

'(1 . 2) с символом кавычки впереди — это сокращенное обозначение (quote (1 . 2)). quote инструктирует оценщика не (!) оценивать прилагаемую форму и просто вернуть ее как есть. Значение этой формы в кавычках — это сама форма. quote говорит: не оценивай. В Common Lisp это можно рассматривать как константные литеральные данные.

(cons 1 2) — это форма Лиспа, которая имеет функцию cons впереди и два аргумента: 1 и 2. Если мы вычислим эту форму, функция cons будет вызвана с аргументом 1 и 2. cons по определению возвращает новую cons-ячейку с ее аргументами как car и cdr. Таким образом, (cons 1 2) возвращает свежую новую ячейку cons, когда мы ее оцениваем.

person Rainer Joswig    schedule 29.07.2011

они не одинаковые и одинаковые.

кавычка (') — это функция, которая говорит: «создать этот список, не оценивая это». пример: '(* 2 2 ) ; Он создаст список ( * 2 2 ) (список (* 2 2) ; Он создаст (4), потому что список оценивается.

функция cons создает связанные пары и только это. Пример: (cons (a b c) (1 2 3) ); создать (ab c . 1 2 3) (cons a (1 2 3 4) ) ; создать (a. 1 2 3 4)

Две функции, которые вы использовали, делают одно и то же в этом случае, но используют разные способы. потому что цитата (') просто создает список перед кавычкой символа ('), а функция cons просто создает связанную пару с "itens", которую вы дали функции.

person FERNANDO MESQUITA    schedule 31.07.2011