Разница между '(1 2 3 4)
и (list 1 2 3 4)
, которые, похоже, возвращают абсолютно одинаковый результат (1 2 3 4)
, не видна, потому что числа в Лиспе оценивают сами себя.
Вместо чисел берут символы или выражения:
(list (+ 1 2) (+ 2 3) (+ 3 4) (+ 4 5))
;; returns/evaluates to:
(3 5 7 9) ;; each of the arguments in a list gets evaluated.
;; while:
'((+ 1 2) (+ 2 3) (+ 3 4) (+ 4 5)) ;; equals to: (quote ((+ 1 2) (+ 2 3) (+ 3 4) (+ 4 5)))
;; returns/evaluates to:
((+ 1 2) (+ 2 3) (+ 3 4) (+ 4 5)) ;; arguments of list not evaluated
;; since `quote` means: take the argument as data - unevaluated.
Теперь вы ясно видите разницу: '(1 2 3 4)
расширяется до (и, следовательно, является синтаксическим сахаром до) (quote (1 2 3 4))
- это специальная форма , тогда как (list 1 2 3 4)
- это функция . Функции в Лиспе оценивают каждый из своих аргументов . Но специальные формы не оценивают каждый из своих аргументов. В случае quote
аргумент quote
не оценивается.
И теперь вы видите, с a
, b
, c
, d
, не определенными ранее, это
'(a b c d)
;; returns: (A B C D)
работает, так как abcd не оценивается!
Но это:
(list a b c d)
вызывает ошибку:
*** - SYSTEM::READ-EVAL-PRINT: variable A has no value
The following restarts are available:
USE-VALUE :R1 Input a value to be used instead of A.
STORE-VALUE :R2 Input a new value for A.
ABORT :R3 Abort main loop
, поскольку ни a
, ни b
, ни c
, ни d
еще не определеныно интерпретатор Lisp пытается их оценить, так как они являются аргументами функции.
Но вы все равно можете получить (A B C D)
, используя функцию list
, заключив в кавычки каждый из аргументов - таким образом, заставив их вычислить их имена символоввместо интерпретатора Lisp для поиска их неопределенных значений:
(list 'a 'b 'c 'd)
;; now it works - though a b c d are not defined yet:
(A B C D)
Примечание: Интересно, что не во всех языках аргументы функции оцениваются только потому, что они являются аргументами функции.В то время как Python оценивает все аргументы своей функции, аналогичные Lisp до ввода и вычисления тела функции, R не делает этого.
Таким образом, оценка аргументов функции является специфическим для Lisp способомобрабатывать аргументы своей функции.(Но он разделяет его с большинством других языков - я просто хочу сказать, что оценка аргументов функции не является общим правилом).И это также фундаментальное различие между макросами Lisp (и специальными формами) и функциями Lisp.В макросах Lisp (и специальных формах) вы можете указать, какие из аргументов функции будут оцениваться в теле макроса, а какие нет.Так что вы имеете полный контроль над оценкой любого из аргументов макроса.В функциях Lisp по умолчанию все аргументы сначала оцениваются перед вводом тела функции.
Это также одна из причин, по которой вам также нужно изучать макросы (которые задают специальные формы) в Lisp.quote
вместе с list
фактически является матерью всех макросов.Любые операции backquote
и unquote
могут быть выражены через quote
и list
(хотя для человеческого читателя это выглядит неприятнее).Можно долго размышлять на эту тему, как вы можете себе представить.И ваш вопрос касается непосредственно сути и сути того, что делает Лисп таким восхитительным.