В чем причина цитирования списков в Common Lisp? [Дубликат]

учебная страница .

Необработанный тип - это имя общего класса или интерфейса без каких-либо аргументов типа. Например, с учетом общего класса Box:

public class Box {
    public void set(T t) { /* ... */ }
    // ...
}

Чтобы создать параметризованный тип поля, вы указываете фактический аргумент типа для параметра формального типа T:

Box intBox = new Box<>();

Если аргумент фактического типа опущен, вы создаете необработанный тип Box:

Box rawBox = new Box();

2
задан Edwin Dalorzo 18 November 2013 в 17:28
поделиться

4 ответа

Исходный код Lisp представлен некоторыми из тех же структур данных, которые используются в программировании Lisp. Особое значение здесь имеют списки и символы. Когда Lisp оценивает форму, которая имеет форму

(quote something)

, то есть, когда Lisp оценивает форму, которая является списком и чей первый элемент является символом quote, тогда он возвращает объект something без его оценки . Таким образом,

(quote 2)       ;=> 2
(quote (a b c)) ;=> (a b c)

Теперь это то, что делает оценщик (или компилятор, & amp; c.), Когда они получают объект Lisp для оценки того, что это список, первый Элемент является символом quote. В качестве программистов Lisp нам еще нужно записать код для читателя Lisp , чтобы прочитать и передать экзалатору. Мы можем записать длинные формы

(quote 2)
(quote (a b c))

в нашем источнике, и читатель Lisp прочитает их и передаст их компилятору, но мы добродетельные программисты , поэтому мы «ленив, и я хочу избежать ввода текста. Таким образом, мы можем ввести

'2
'(a b c)

. Компилятор получает точно такой же ввод; список, первым элементом которого является символ quote, вторым значением которого является 2 или (a b c).

Теперь мы можем поговорить о вашем коде. Форма

(list 'quote x)

возвращает список, первым элементом которого является символ quote, а вторым элементом является значение переменной x. Это может быть напечатано как

(quote <value-of-x>) ; fill in x's value for <value-of-x>, of course

Теперь принтер Lisp немного умный и имеет возможность печатать такие вещи, используя ту же стенографию, что нам разрешено использовать, когда мы пишем источник. Так что это также можно напечатать как

'<value-of-x>

Теперь у нас есть достаточно, чтобы ответить на ваш вопрос о коде книги:

Теперь, интересно, вышеприведенная функция не возвращать список, а просто цитирует все, что я передаю ему. И поэтому, если я его назову

(quote-it east), он просто вернет 'east, а не ('east)

Поскольку 'east является аббревиатурой для (quote east) ], теперь мы видим, что (quote-it east) действительно возвращает список. И это список формы, которую вы ожидаете: список, первым элементом которого является символ quote, вторым элементом которого является символ east. Если возвратил ('east), он все равно будет возвращать список, но он будет возвращать список неправильной формы. ('east), когда мы расширим аббревиатуру, список ((quote east)); то есть это список одного элемента, а этот элемент - другой список, первым элементом которого является символ quote, а вторым элементом является символ east. Это, безусловно, список, но это не тот список, который вы искали.

Теперь мы можем взглянуть на ваш предлагаемый код. Ваша функция quote-it работает только в том случае, если вы вызываете (quote-it 'x). То есть вы можете сделать

(quote-it 'x)
;=> x

, но обратите внимание, что вы получаете символ , и вы получаете символ x назад. Вы не получаете список, первым элементом которого является символ quote, а вторым элементом является <value-of-x>. Когда вы используете quote-it с другими значениями, вы увидите проблему:

(quote-it 2)
;=> x

Вы все еще вернули символ, потому что

(defun quote-it (x) 
  (quote x))         ; or 'x

Принимает аргумент, привязывает его к лексической переменной x, а затем возвращает значение (quote x). Какова ценность (quote x)? Как объяснялось ранее, когда оценщик (или компилятор, & amp; c.) Получает список символов quote и something, значение является литералом something. Поскольку тело quote-it является списком символа quote и символом x, значение тела quote-it является символом x.

6
ответ дан Joshua Taylor 21 August 2018 в 19:40
поделиться
  • 1
    +1 Отличный ответ. Это именно то, что я искал. Теперь все ясно. Это часами меня било. Спасибо, Джошуа! – Edwin Dalorzo 18 November 2013 в 17:09
  • 2
    @EdwinDalorzo Рад быть 'help! – Joshua Taylor 18 November 2013 в 17:09

В Lisp есть списки, например: (mary выбрасывает мяч).

В некоторых списках описывается вычисление, например: (* pi (+ rr))

а второй - выражение, подходящее для того, чтобы оценщик мог пережевывать.

Но нам нужен способ включения данных в выражения. Итак, несколько десятилетий назад был введен специальный оператор, который позволил бы это сделать, например: (count-существительные (цитата (mary бросила мяч)))

Прошло время, и разработчикам надоело писать (цитата ... ), поэтому они изобрели короткую нотную запись: (count-существительные (mary бросили мяч)).

В эти дни стенография выполняется во время чтения, так как символы считываются из файла или от терминала. Это делается с помощью средства, известного как «считывающие макросы». Это имя сбивает с толку большинство новичков, поскольку на языке, называемом «макросы», есть еще одно средство, которое действительно имеет мало общего с чтением файлов. Они обычно используются для добавления небольшого синтаксического сахара. Как в этом примере цитаты. После того, как поток файлов (или терминалов) был прочитан, все это всего лишь список.

Вы заметите, что если вы введете: (quote bob) в свой запрос lisp, вы вернетесь: 'bob. Принтер хорошо осведомлен о соглашении, которое (quote bob) имеет сокращенную форму. Если вы когда-нибудь решите написать свои собственные макросы читателей, вы можете научить принтер, как играть.

Макросы, как v.s. читайте макросы, позвольте вам представить свои собственные специальные операторы. И это позволяет вам встраивать пользовательские языки, специфичные для домена, в ваш код. Итак - вид макроса позволяет расширять семантику и макросы чтения, чтобы вы могли расширить синтаксис. Макросы влияют на поведение компилятора и оценщика.

2
ответ дан Ben Hyde 21 August 2018 в 19:40
поделиться

Вас смущает макрос читателя. Верхний уровень Lisp читается / eval / print, если вы читаете '(foo bar), который вы получаете (quote (foo bar)), если вы eval (quote (foo bar)) вы получаете (foo bar)

0
ответ дан ddyer 21 August 2018 в 19:40
поделиться
  • 1
    Я не понимаю, как это объясняет, что (list 'quote x) оценивает цитату, а не список. – Edwin Dalorzo 18 November 2013 в 15:12
  • 2
    @EdwinDalorzo (list x y) возвращает список, который будет напечатан как (<value-of-x> <value-of-y). Таким образом, (list 'quote y) вернет список, который будет напечатан как (quote <value-of-y>). Теперь принтер lisp может сокращать (quote <value-of-y>) как '<value-of-y>. Форма '<value-of-y> представляет собой список. Это список, первым элементом которого является символ quote, вторым элементом которого является <value-of-y>. – Joshua Taylor 18 November 2013 в 16:50

Пример. Если вы хотите построить список с символом foo и номером переменной:

  • , у нас есть номер
  • , мы хотим составить список (foo <some-number>)

Теперь мы напишем для него функцию:

(defun foo-it (n)
  (list 'foo n))

Очевидно

(defun foo-it-1 (n)
  (foo n))

Не будет работать. Он будет вызывать функцию FOO на n вместо построения списка.

(defun foo-it-2 (n)
  '(foo n))

Выше также не будет работать, поскольку список (foo n) не оценивается и не возвращается как есть.

Теперь Lisp имеет синтаксис backquote:

(defun foo-it-3 (n)
  `(foo ,n))

Выше будет работать. Запятая отмечает, что будет оценен символ n.

Для вашей проблемы. Замените foo на quote:

(list 'foo n)  ->   (list 'quote n)

или

`(foo ,n)    ->     `(quote ,n)

Основное отличие заключается в том, что принтер Lisp всегда будет печатать (foo 3) как (foo 3). FOO не имеет специальной цели. Но QUOTE имеет (поскольку он определен на языке), и принтер Lisp может печатать (quote 3) как '3.

Пример:

CL-USER 14 > (progn
               (write (list 'foo 3) :pretty nil)
               (terpri)
               (write (list 'foo 3) :pretty t)
               (values))
(FOO 3)
(FOO 3)

CL-USER 15 > (progn
               (write (list 'quote 3) :pretty nil)
               (terpri)
               (write (list 'quote 3) :pretty t)
               (values))
(QUOTE 3)
'3

Это просто потому, что в Lisp символ quote определяется встроенным синтаксисом, и принтер знает об этом.

Также обратите внимание, что печать также изменяется набором специальных символов, таких как *print-pretty*, *print-readably*, .... Так что разные настройки Lisp могут печатать разные, основываясь на настройках этих переменных.

4
ответ дан Rainer Joswig 21 August 2018 в 19:40
поделиться
  • 1
    Еще одно замечательное объяснение. Вот, мой голос +1 – Edwin Dalorzo 18 November 2013 в 22:42