Значение цитаты в Лиспе

Этот вопрос возник при чтении SICP. Почему (list 'quote '(a b c)) оценивается интерпретатором (R5RS в Dr.Racket) как '(a b c). Для меня это должно быть (quote (a b c)). Например, (list 'quot '(a b c)) оценивается как (quot (a b c)). Что такого особенного в 'quote?


person Graduate    schedule 17.12.2013    source источник
comment
Какой интерпретатор вы используете?   -  person Óscar López    schedule 17.12.2013
comment
Поскольку другие ответы по существу дублируются, я добавлю это здесь, чтобы добавить к тому, что они говорят: даже когда вы смотрите на синтаксис с одинарными кавычками, вы действительно видите непустой list: (consp ''42) истинно (возвращает не-nil).   -  person Drew    schedule 18.12.2013


Ответы (4)


Мне также потребовалось некоторое время, чтобы понять эту проблему. Но это всего лишь ваш добросердечный интерпретатор шепелявости, показывающий (цитата (a b c)) в эквивалентной форме '(a b c). Поскольку такой эквивалентности/синтаксического сахара для (quott (a b c)) не существует, он показан как есть.

person AlbusMPiroglu    schedule 17.12.2013
comment
Кажется, я начинаю понимать. Если A = (quote (a b c)), и B = '(a b c), и A равно B, и они представлены одинаково. Таким образом, (quote A) должно быть равно (quote B) и представлено таким же образом. - person Graduate; 18.12.2013
comment
@Graduate (quote A) не равен (quote B), поскольку quote не оценивает параметры. В итоге вы получите символ A и символ B, которые позже могут быть оценены как одно и то же, но цитата не оценивается. - person Loïc Faure-Lacroix; 18.12.2013
comment
Вы также можете изучить стандартный универсальный метод print-object. Если вы defmethod print-object для своих собственных классов, Лисп-принтер (тот же принтер, который печатает (quote) как ' ) будет печатать ваш объект так, как вы этого хотите, везде. Я только что попробовал перегрузить print-object для символа 'quote и, что интересно, это ничего не изменило для sbcl, но работало на LispWorks. Я не знал, что это было неопределенное поведение по стандарту, и даже зарегистрировал ошибку для sbcl, которая, к счастью, вскоре была отклонена :/ - person AlbusMPiroglu; 26.12.2013

Вы получите различное поведение в зависимости от того, какой именно Лисп вы используете (Scheme, Racket, Common Lisp и т. д.), но в целом система примет 'x как сокращение или синтаксический сахар для (quote x). Эти две формы полностью эквивалентны, и их значения одинаковы: невычисленное x. Когда результат выходит из системы, она может выбрать печать первым способом, чтобы сделать результат более интуитивно понятным для пользователя. То же самое происходит и с cons. Например,

(cons 1 2)
;=> (1 . 2)

потому что это общий способ печати ячеек cons (пар). Однако существует особый случай, когда второй частью пары является другой список (либо пустой список (), либо другая пара, и поэтому мы имеем следующее. Я также написал немного больше о том, как списки и cons-ячейки печатаются в ответе на Рекурсивный диапазон в Lisp добавляет точку?.

(cons 1 '())
;=> (1)

(cons 1 '(2 3))
;=> (1 2 3)

Теперь я записал значения приведенного выше выражения. Например, значение формы (cons 1 '(2 3)) — это список (1 2 3). В качестве дополнительной сложности некоторые системы (я имею в виду некоторые языки, в частности Dr. Racket) не печатают значение формы в интерактивной подсказке, а печатают форму, которая будут давать одни и те же (для некоторых интерпретаций «те же самые») значения. Например, вы можете вычислить '(1 . 2) и увидеть результат (cons 1 2), потому что это другая форма, которая выдаст такое же значение. Это может быть полезно, если вы занимаетесь чистым функциональным программированием с ссылочная прозрачность, но если вы этого не ожидаете, это может привести к некоторой путанице.

Хороший способ убедиться в том, что мы получаем нужные результаты, независимо от того, как система их выводит, — это проверить их. Мы ожидаем, что (list 'quote '(a b c)) должен вернуть список, где car — это символ quote, а cadr — это список (a b c). Вот что мы получаем (в Dr. Racket 5.3 с языком R5RS):

> (display (list 'quote '(a b c)))
'(a b c)
> (display (car (list 'quote '(a b c))))
quote
> (display (cadr (list 'quote '(a b c))))
(a b c)

Аналогичные результаты мы получим, если будем использовать 'qmmmt вместо 'quote:

> (display (list 'qmmmt '(a b c)))
(qmmmt (a b c))
> (display (car (list 'qmmmt '(a b c))))
qmmmt
> (display (cadr (list 'qmmmt '(a b c))))
(a b c)

Единственное отличие состоит в том, что в первом случае display отображает список, car которого является символом quote, используя сокращение, доступное для таких списков. То есть вместо отображения (quote (a b c)) отображалось '(a b c).

person Joshua Taylor    schedule 17.12.2013

'(a b c) и (quote (a b c)) на самом деле разные обозначения одного и того же. Так что не удивляйтесь, если ваш Lisp напечатает более короткую версию.

В целом '<something> совпадает с (quote <something>).

QUOTE используется в Лиспе для обозначения выражений, которые должны оцениваться сами по себе. Обычно список представляет собой вызов функции или макроса, а символ — переменную. Если вы хотите рассматривать их как данные, вам нужно указать их.

Так как (quote <something>) так часто используется в Лиспе, была введена сокращенная версия '<something>, чтобы сэкономить время при наборе текста или чтении...

person Rainer Joswig    schedule 17.12.2013
comment
Я хочу подчеркнуть, что в вопросе я использую 'quote, а не quote. И 'quote представлено по-другому, не так, как 'qmmmt например. - person Graduate; 18.12.2013
comment
Например, (list 'quote '(a b c)) представлен как '(a b c), (list 'c 'quote '(a b c)) представлен как (c quote (a b c)), (list 'quo '(a b c)) представлен как (quo (a b c)) - person Graduate; 18.12.2013
comment
@Graduate система может распечатать список (quote abc) и список (qmmmt abc) по-разному (как 'abc и (qmmmt abc)) соответственно, но оба являются списками; если вы вызовете для них first и second, вы увидите ожидаемые значения. Это всего лишь вопрос печати. - person Joshua Taylor; 18.12.2013
comment
Мне просто было интересно, почему он печатает по-разному. - person Graduate; 18.12.2013

display излучает некоторые поведения. Например. '(a . (b . (c . ()))) отображается (a b c). 'quote отображается quote и, возможно, '(quote x y) отображается (quote x y), а '(quote x) отображается 'x или (quote x). Какой из них зависит от реализации, но оба означают одно и то же.

Как данные (т.е. в кавычках, как (quote quote) и его аббревиатура 'quote) результат оценки, символ quote не является чем-то особенным для любого LISP, точно так же, как '+ и 'potato оказываются символами + и potato. Любой символ, который что-то означает, если не цитируется, в кавычках не является особенным.

person Sylwester    schedule 17.12.2013
comment
Очень важно четко указать, что вы помещаете в свои блоки кода: значения или формы. Когда вы говорите, что (quote quote) сокращенно 'quote, вы говорите о значении, которое представляет собой список длины два, каждый из элементов которого является символом quote. Когда вы говорите, что '+ и 'potato являются символами, вы имеете в виду, что формы '+ и 'potato при вычислении дают значения, которые являются символом + и символом potato. Обычно смысл ясен из контекста, но это вопрос о том, что вещи означают в разных контекстах. - person Joshua Taylor; 18.12.2013
comment
@JoshuaTaylor С (quote quote) я думал как о форме .. например. кавычка привязана к специальной форме и что ее приложение превратило форму в (без специального) символа quote, точно так же, как '+ превращается в неспециальный символ, поскольку он заключен в кавычки при оценке +, это совсем другое. Программисту на алголе, как мне, нелегко найти аналогию для этого, поэтому потребовалось некоторое время, чтобы привыкнуть к этому :) - person Sylwester; 18.12.2013