Простой вопрос о Lisp Case - проблема по сравнению с nil - PullRequest
3 голосов
/ 23 мая 2011

Я пытаюсь использовать оператор case, чтобы сделать некоторый код более читабельным. Кажется, он работает как серия операторов if, но по какой-то причине оператор case всегда принимает сравнение с нулем, даже если оно не соответствует действительности. Может кто-нибудь уточнить, почему происходит такое поведение?

Пример:

> (case 'a            
    (nil nil)         
    (otherwise 'b))   
NIL                   
> (case 'a            
    ('a 'b)           
    (otherwise nil))  
B                       

В приведенном выше примере первый экземпляр возвращает ноль, хотя «явно не ноль. Попытка сделать то же самое, если оператор ведет себя так, как я ожидал:

> (if (eq 'a nil) nil 'b)    
B                            
> (if (eq 'a 'a) 'b nil)     
B                            

Я предполагаю, что в отношении заявления по делу есть какое-то поведение, которое я не понимаю. Любая помощь будет оценена.

Edit: Просто чтобы уточнить, я знаю, что «не будет оцениваться. Я просто смоделировал этот пример, чтобы создать ситуацию, в которой целью оператора case было определенно НЕ ноль.

Я использую xlisp-plus, но собираюсь попробовать настоящую установку clisp и посмотреть, будет ли она вести себя по-другому.

Изменить (еще раз): Установил CLISP и там все отлично работает. Не стоит беспокоиться, чтобы выяснить, почему xlisp отличается. Спасибо всем за проверку работоспособности.

Ответы [ 5 ]

3 голосов
/ 23 мая 2011

Каждая из ключевых спецификаций в CASE может быть либо списком литералов, либо отдельным атомом. Однако CLtL говорит, что атом не должен быть NIL, так как он неоднозначен относительно того, является ли он литералом NIL или пустым списком. Вместо этого используйте список NIL:

> (case 'a
    ((nil) nil)         
    (otherwise 'b))
B
> (case nil
    ((nil) nil)         
    (otherwise 'b))
NIL
2 голосов
/ 23 мая 2011

Common Lisp ожидает, что CASE будет проверять элемент на атом или список атомов. В тесте также есть функция EQL.

(case 'a
  (a 'b)    ; EQL a
  (otherwise 'foo))

(case 'a
  ((a b c) 'foo)   ; EQL to one of a, b or c
  (otherwise 'bar))

Цитируется только для работ случайно. Не используйте его:

; don't use this:
(case 'a
  ('a 'foo)    ; <- bad!  , EQL to QUOTE or A
  (otherwise 'bar))

Выше указано то же самое:

; don't use this:
(case 'a
  ((quote a) 'foo)   ; <- bad! ,  EQL to QUOTE or A
  (otherwise 'bar))
1 голос
/ 23 мая 2011

То же самое здесь с SBCL:

CL-USER> (case 'a
           (nil nil)
           (otherwise 'b))
B

Тем не менее, 'a является символом и поэтому никогда не может быть nil.

1 голос
/ 23 мая 2011

я думаю, что это зависит от вашей версии LISP. У меня есть LispWorks на Mac и мой результат:

CL-USER 2 : 1 > (case 'a            
    (nil nil)         
    (otherwise 'b))   
B
0 голосов
/ 23 мая 2011

Значения в форме case являются неявно заключенными в кавычки списками литералов, поэтому это:

(case 'a
  ((a) 'b)
  (otherwise nil))

это то, что вы хотите. otherwise должно работать (как говорили другие) - вместо этого попробуйте t.

Кстати, когда вы использовали 'a, читатель читает его как (quote a), что означает, что он также выберет его, когда значение равно quote, например:

(case 'quote
  ('a 'b)
  (otherwise nil))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...