Почему ноль не может быть сопоставлено в случае / ecase? - PullRequest
0 голосов
/ 10 января 2019

Следующая форма

(let ((foo nil))
  (ecase foo
    (:bar 1)
    (:baz 2)
    (nil 3)))

выдает ошибку NIL fell through ECASE expression. Обходной путь для этого заключается в том, чтобы обернуть nil регистр круглыми скобками, например:

(let ((foo nil))
  (ecase foo
    (:bar 1)
    (:baz 2)
    ((nil) 3))) ;; => 3

но почему первый пример не работает? Имеет ли распакованный nil чехол какое-то особое значение?

1 Ответ

0 голосов
/ 10 января 2019

Каждый пункт в case может соответствовать одному элементу или списку элементов, например, Вы можете написать:

(ecase foo
  (:bar 1) ;; match a specific symbol
  ((:baz :quux) 2)) ;; match either of these symbols

NIL также является пустым списком в Лиспе, и когда он используется в качестве теста в case, это то, как он обрабатывается, поэтому он никогда ничего не соответствует. Аналогично, T и OTHERWISE используются для указания регистра по умолчанию, поэтому вы не можете сопоставить их как отдельные элементы. Чтобы соответствовать любому из них, вам нужно поместить их в список.

С технической точки зрения, спецификация говорит о ключах в предложении:

keys --- обозначение для списка объектов. В этом случае символы t и otherwise не могут использоваться в качестве обозначения клавиш. Чтобы обозначить эти символы как ключи, вместо них должны использоваться обозначения (t) и (otherwise) соответственно.

и определение списка обозначений гласит:

обозначение для списка объектов; то есть объект, который обозначает список и который является одним из: ненулевой атом (обозначает одноэлементный список, элемент которого является ненулевым атомом) или правильный список (обозначает себя).

Обратите внимание, что случай, когда отдельный атом обрабатывается как одноэлементный список, говорит "ненулевой атом". Это позволяет NIL попасть во второй случай, когда правильный список обозначает себя. В противном случае не было бы никакого способа создать указатель списка для пустого списка, так как NIL будет означать (NIL).

Вы могли бы утверждать, что нет никакого смысла иметь пустой список ключей в CASE, так как он никогда ничего не будет соответствовать, и весь пункт может быть просто опущен. Этот вырожденный случай полезен для автоматической генерации кода (например, других макросов, которые расширяются до CASE), поскольку они могут создавать пустые списки, и их следует обрабатывать согласованно с другим списком. Им было бы сложнее сделать генерацию предложения условной относительно наличия каких-либо ключей.

...