Необработанный тип - это имя общего класса или интерфейса без каких-либо аргументов типа. Например, с учетом общего класса Box:
public class Box {
public void set(T t) { /* ... */ }
// ...
}
Чтобы создать параметризованный тип поля, вы указываете фактический аргумент типа для параметра формального типа T:
Box intBox = new Box<>();
Если аргумент фактического типа опущен, вы создаете необработанный тип Box:
Box rawBox = new Box();
Исходный код 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
.
В Lisp есть списки, например: (mary выбрасывает мяч).
В некоторых списках описывается вычисление, например: (* pi (+ rr))
а второй - выражение, подходящее для того, чтобы оценщик мог пережевывать.
Но нам нужен способ включения данных в выражения. Итак, несколько десятилетий назад был введен специальный оператор, который позволил бы это сделать, например: (count-существительные (цитата (mary бросила мяч)))
Прошло время, и разработчикам надоело писать (цитата ... ), поэтому они изобрели короткую нотную запись: (count-существительные (mary бросили мяч)).
В эти дни стенография выполняется во время чтения, так как символы считываются из файла или от терминала. Это делается с помощью средства, известного как «считывающие макросы». Это имя сбивает с толку большинство новичков, поскольку на языке, называемом «макросы», есть еще одно средство, которое действительно имеет мало общего с чтением файлов. Они обычно используются для добавления небольшого синтаксического сахара. Как в этом примере цитаты. После того, как поток файлов (или терминалов) был прочитан, все это всего лишь список.
Вы заметите, что если вы введете: (quote bob) в свой запрос lisp, вы вернетесь: 'bob. Принтер хорошо осведомлен о соглашении, которое (quote bob) имеет сокращенную форму. Если вы когда-нибудь решите написать свои собственные макросы читателей, вы можете научить принтер, как играть.
Макросы, как v.s. читайте макросы, позвольте вам представить свои собственные специальные операторы. И это позволяет вам встраивать пользовательские языки, специфичные для домена, в ваш код. Итак - вид макроса позволяет расширять семантику и макросы чтения, чтобы вы могли расширить синтаксис. Макросы влияют на поведение компилятора и оценщика.
Вас смущает макрос читателя. Верхний уровень Lisp читается / eval / print, если вы читаете '(foo bar), который вы получаете (quote (foo bar)), если вы eval (quote (foo bar)) вы получаете (foo bar)
(list 'quote x)
оценивает цитату, а не список.
– Edwin Dalorzo
18 November 2013 в 15:12
(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>
представляет собой i> список. Это список, первым элементом которого является символ 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 могут печатать разные, основываясь на настройках этих переменных.
'help
! – Joshua Taylor 18 November 2013 в 17:09