Значение на „цитат“ в Lisp

Този въпрос възникна при четене на 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
Тъй като другите отговори са по същество дубликати, ще добавя това тук, за да добавя към това, което казват: Дори когато разглеждате синтаксиса с единични кавички, това, което наистина виждате, е непразно списък: (consp ''42) е вярно (връща не-nil).   -  person Drew    schedule 18.12.2013


Отговори (4)


Също така ми отне известно време, за да разбера този проблем. Но това е просто вашият добродушен интерпретатор на lisp, който показва (цитат (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 за вашите собствени класове, Lisp-принтерът (същият принтер, който отпечатва (quote) като ' ), ще отпечата вашия обект както искате, навсякъде. Току-що се опитах да претоваря печатен обект за символ 'quote и интересното е, че не промени нищо за sbcl, но работеше в LispWorks. Не знаех, че това е недефинирано поведение от стандарта и дори подадох бъг за sbcl, който за щастие беше отхвърлен достатъчно скоро:/ - person AlbusMPiroglu; 26.12.2013

Ще получите различни поведения в зависимост от това какъв точно Lisp използвате (Scheme, Racket, Common Lisp и т.н.), но като цяло системата ще приеме 'x като стенографско или синтактично захарза (quote x). Двете форми са напълно еквивалентни и стойностите им са еднакви: неоцененото x. Когато резултатът излиза от системата, тя може да избере да отпечата по първия начин, за да направи резултата по-интуитивен за потребителя. Подобно нещо се случва и с cons. Например,

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

тъй като това е общият начин, по който се отпечатват 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 се използва в Lisp за маркиране на изрази, които трябва да се оценяват сами. Обикновено списъкът би бил функция или макро извикване, а символът би бил променлива. Ако искате да ги третирате като данни, трябва да ги цитирате.

Тъй като (quote <something>) се използва толкова често в Lisp, съкратената версия '<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 е обвързан със специален формуляр и че приложението му е превърнало формуляра в (без специален) символ quote, точно както '+ се превръща в неспециален символ, тъй като е цитиран, докато оценяването на + е съвсем различно. Не е лесно за програмист на алгол като мен да намери аналогия за това, така че отне известно време да свикна :) - person Sylwester; 18.12.2013