Почему, согласно этой книге, композиция двух функций not в CL приводит к нулю?

Я изучаю книгу Common LISP: A Gentle Introduction to Symbolic Computation. Книге около 40 лет, и, судя по всему, она в некотором роде классика.

В главе 1 автор использует блоки как способ объяснения функций с входами и выходами. Это один из рисунков: введите здесь описание изображения

На самом деле рисунок выше является ответом на этот вопрос. Я получил первый и второй вопрос: введите здесь описание изображения

Однако третий вопрос кажется странным: введите здесь описание изображения

Состав (не (не...)) зависит от... переменной части. Например, терминал показывает:

CL-USER> (not (not 12))
T
CL-USER> (not (not nil))
NIL

Это книжное упражнение кажется в чем-то неправильным. Но, поскольку я мало что знаю о CL, я подумал, что было бы лучше спросить, не считают ли более опытные разработчики CL это странным пунктом в листе ответов.

Я использую SBCL, Slime и Common Lisp. Я новичок в CL, но у меня есть некоторый опыт в Racket.

заранее спасибо


person Pedro Delfino    schedule 14.05.2021    source источник


Ответы (3)


Упражнение 1.14:

На самом деле автор хочет, чтобы мы использовали символ NOT в качестве входных данных для функции NOT. Входными данными являются не функция с именем NOT и не переменная с именем NOT. Таким образом, символ должен быть заключен в кавычки в вычислении:

> (NOT 'NOT)
NIL

Поскольку каждый символ является истинным, отсутствие истинного является ложным. false в Common Lisp — это символ NIL.

Чем отличаются символы NIL и NOT?

  • NIL оценивает саму себя
  • NOT не имеет значения по умолчанию и оценивается как переменная. Чтобы вычислить символ NOT самому себе, его нужно заключить в кавычки.

Это объясняется в главе 3.8 ИСПОЛЬЗОВАНИЕ СИМВОЛОВ И СПИСКОВ В КАЧЕСТВЕ ДАННЫХ в старой редакции.

person Rainer Joswig    schedule 15.05.2021
comment
ага, имеет смысл. (никогда не верьте утверждению ОП без проверки!) Если бы они только включили предыдущий пример FRED --> [ NOT ] --> NIL, это было бы намного яснее. это так рано в книге, где все еще имеет дело только с символами и числами... - person Will Ness; 15.05.2021

В упражнении не показан состав функций; он показывает применение функции not к аргументу not. В Common Lisp все значения верны, кроме nil (а также 'nil, () и '()), поэтому применение not к not должно дать nil.

Есть предостережение: not — это функция в Common Lisp, но в CL есть несколько пространств имен. Если вы хотите попробовать это в REPL, вам нужно указать, что вы имеете в виду функцию not, а не переменную not, используя либо function, либо #' (прямая кавычка). ):

CL-USER> (not (function not))
NIL
CL-USER> (not #'not)
NIL
CL-USER> (not not)  ; --> The variable NOT is unbound.

Хм. Некоторым из нас было слишком лень искать упражнение в книге; похоже, что в этом месте книги обсуждались только цифры и символы (да!). Автор хотел, чтобы not был символом, а это значит, что он должен быть заключен в кавычки при вызове функции.

Поскольку not — это функция, она оценивает свои аргументы. Вызов (not not) оценивает аргумент not, но not является несвязанной переменной, поэтому выдается ошибка. Чтобы передать символ not функции not, аргумент должен быть заключен в кавычки либо с quote (что является не функцией, а специальный оператор: quote не оценивает свои аргументы) или кавычки ('). Цитата not оценивается как символ:

CL-USER> not  ;  -->  The variable NOT is unbound.
CL-USER> (quote not)
NOT
CL-USER> 'not
NOT
CL-USER> (symbolp 'not)
T
CL-USER> (not 'not)
NIL

Поскольку nil — единственный символ, который является ложным в логическом контексте, символ not должен быть истинным, поэтому (not 'not) должен быть ложным.

person ad absurdum    schedule 14.05.2021
comment
Спасибо. Я пробовал CL-USER› (не не); --› Переменная NOT не привязана. Я думал, что это никак не исправить. Не знал о #' . Спасибо. - person Pedro Delfino; 15.05.2021

Это не композиция. это вызов функции

(not not)

Функция not получает в качестве аргумента значение, являющееся функцией not. Поскольку это значение не равно NIL, возвращаемое значение равно NIL:

not:
--------------------
NIL      --->   T           (not NIL)
non-NIL  --->   NIL         (not T), (not 1), (not not), (not (list 1)), ...
--------------------

Любое значение, отличное от NIL, является истинным, поэтому not возвращает для него NIL.

Конечно, (not not) работает в Scheme, то есть в Lisp-1. В Common Lisp, который является Lisp-2, вызов (not #'not).

update: вызов на самом деле (not 'not), точно так же, как код предыдущего примера в книге — (not 'fred).

person Will Ness    schedule 14.05.2021