Когда вы говорите, что этот диалект "не имеет переменной NIL", вы правы в двух отношениях. Мало того, что nil
не существует, он, кажется, рассматривается как обычный символ, который вы можете использовать в качестве переменной. Там написано «Переменная не определена».
В диалектах Лисп, где nil
имеет особое значение, nil
обычно нельзя использовать в качестве переменной.
nil
эквивалентно ()
только в «классических» Лиспах (мой термин). Под этим я подразумеваю Лисп, который связан по происхождению или подражанию с оригинальным Джоном Маккарти Лиспом. Emacs Lisp и Common Lisp именно таковы. Классический Лисп использует nil
в качестве ограничителя списка: то есть (cons 1 nil)
создает список (1)
Схема не является классическим Лиспом в этом смысле. Там нет nil
. Он использует ()
в качестве печатной нотации для пустого списка, и когда вы хотите, чтобы это значение в выражении, оно заключалось в кавычки, как непустой литерал списка: '()
. На схеме (cons 1 nil)
написано (cons 1 '())
. Логическое значение false представлено объектом, обозначенным #f
. Пустой список - это истина, а не ложь, поэтому (if '() 1 2)
дает 1, а не 2, как в классическом Лиспе. Ни '()
, ни #f
не являются символами.
Схема также чувствительна к регистру. Даже если у вас есть переменная NIL
в схеме, она не имеет ничего общего с nil
. Вы можете использовать оба в качестве имен переменных.
Текст SICP вызывает путаницу в этой теме, поскольку в его первых главах делается ссылка на переменную с именем nil
, которая содержит значение '()
. В схеме нет такой переменной; Вы должны сделать это самостоятельно, если хотите, чтобы эти примеры работали. Это неудачный аспект учебника.
Если вы определяете переменную nil
, значением которой является объект '()
, так что код главы 2 из SICP работает, он все равно не эквивалентен пустому списку, как в классическом Лиспе, потому что в классический Лисп, nil
и ()
- эквивалентные обозначения для символа. Сам символ nil
является пустым списком, и наоборот. Это не имя переменной, которая просто содержит список. И поэтому выражение кавычки 'nil
также приводит к пустому списку! Тогда как в схеме 'nil
вычисляется обычный символ nil
, даже если вы определили его как переменную, содержащую пустой список.
Относительно второго вопроса: «(), кажется, работает, имеют ли оба значения одинаковое значение?». Аспект «того же значения» описан выше: нет, это не то же самое значение в Схеме. Насколько это работает, рассмотрим следующую цитату из отчета схемы R5RS:
Примечание: во многих диалектах Лисп пустая комбинация () является допустимым выражением. В схеме комбинации должны иметь хотя бы одно подвыражение, поэтому () не является синтаксически допустимым выражением. [4.1.3 Процедурные вызовы]
Таким образом, эта неуклюжая трактовка ()
как допустимого выражения, создающего пустой список, представляется расширением поведения схемы ПК, а не стандартной схемой. Он принимает выражение, которое не является синтаксически допустимым выражением Scheme.