Паренс "варианты" с оператором cond? - PullRequest
0 голосов
/ 09 июля 2019

Я решил, что приведу в порядок следующую функцию.Идея в том, что он использует cond, но также содержит if s, что затрудняет когнитивную обработку.Это bst код из книги ansi common lisp.

(defun percolate (bst)                      
  (cond ((null (node-l bst))                
         (if (null (node-r bst))
             nil
             (rperc bst)))
        ((null (node-r bst)) (lperc bst))
        (t (if (zerop (random 2))
               (lperc bst)
               (rperc bst)))))

Моя идея заключалась в том, чтобы удалить if, добавив больше случаев в cond, а затем обосновать все это с помощью причины слева,эффект справа.Вот что я придумал:

(defun percolate (bst)                      ; [6,7,7a]
  (cond (((and (null (node-l bst)) (null (node-r bst)))  nil)
         ((null (node-l bst))                            (rperc bst))
         ((null (node-r bst))                            (lperc bst))
         (t                                              (if (zerop (random 2))
                                                             (lperc bst)
                                                             (rperc bst))))))

Однако, это приводит к ошибке

*** - SYSTEM::%EXPAND-FORM: (AND (NULL (NODE-L BST)) (NULL (NODE-R BST))) should be a
      lambda expression

Я могу найти другие сообщения об этой проблеме при переполнении стека, например здесь но я до сих пор не понимаю этого.Является ли cond отклонением от нормального синтаксиса lisp?Я хотел бы указать на мое предположение, которое ошибочно.

Для записи интерпретатор принимает следующий код, но, очевидно, мы не хотим его так писать.

(defun percolate (bst)                      ; [6,7,7a]
  (let ((both-null (and (null (node-l bst)) (null (node-r bst))))
        (l-null    (null (node-l bst)))
        (r-null    (null (node-r bst))))
  (cond ((both-null                                              nil)
         (l-null                                         (rperc bst))
         (r-null                                         (lperc bst))
         (t                                              (if (zerop (random 2))
                                                             (lperc bst)
                                                             (rperc bst)))))))

Ответы [ 2 ]

4 голосов
/ 09 июля 2019

cond синтаксис:

cond {clause}*

clause::= (test-form form*) 

примеры

(cond (var)
      (var a b c)
      (var (f a) (f b) (f c))
      ((and var-a var-b) (f c) (f d))
      ((f a) b (f c) d)
      (t (f a) (f b) (f c)))

Средства:

  • ноль или более предложений.
  • каждое предложение находится внутри списка и начинается с тестовой формы, а затем с нуля или более форм

let синтаксис:

let ({var | (var [init-form])}*)
  declaration*
  form*

Означает:

  • ноль или более предложений переменных внутри одного списка
  • каждое предложение переменной является либо переменной, либо списком переменных и необязательной init-form
  • за списком переменных присваивается необязательный ноль или более объявлений, а затем ноль или более форм тела

Пример:

(let ()
   )

(let (a)
  a)

(let (a
      (b t))
  (and a b))

(let ((a t)
      (b (not t)))
  (or a b))
0 голосов
/ 09 июля 2019

Я определил возможный ответ в ходе написания поста.

Я все же сделаю пост, хотя было бы здорово получить дальнейшие разъяснения и обсуждения.

ПозволяетСначала заявите, что мы знаем.При let необходимо иметь пару окружающих паренсов, чтобы содержать все присвоенные отдельные лексические переменные:

(let ((both-null (and (null (node-l bst)) (null (node-r bst))))
      (l-null    (null (node-l bst)))
      (r-null    (null (node-r bst))))

Но оказывается, что допущение cond следует тому жеобразец (который я предположил).

Конд работает очень хорошо без окружающих паренов.Следующая форма принята переводчиком:

(defun percolate (bst)                      ; [6,7,7a]
  (cond ((and (null (node-l bst)) (null (node-r bst)))  nil)
        ((null (node-l bst))                            (rperc bst))
        ((null (node-r bst))                            (lperc bst))
        (t                                              (if (zerop (random 2))
                                                            (lperc bst)
                                                            (rperc bst)))))

Однако (вот та часть, которая меня укусила), оказывается, переводчик приметдополнительные символы , если кто-то невольно копирует синтаксис let form.

... , кроме случаев!- первая форма в одном из выражений cond сама по себе является сложной формой, то есть не атомом.

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

ОБНОВЛЕНИЕ : мой тест на достоверность этих форм состоял в том, чтобы вставить их в REPL.Оказывается, этого недостаточно, вы должны скомпилировать, как объяснено в комментариях Райнера Йосвига.

Итак, некоторые выводы

  • MakeОбязательно помните, что cond не следует синтаксической модели let
  • Будьте осторожны, потому что, если вы впадете в это предположение, вы можете сойти с ним на некоторое время, а потом вдруг это не сработает по причине, указанной выше.
  • Если вы пишете cond с дополнительными паренами, практикуйте его правильно и учитесь распознавать его без.
...