Распространенная ошибка lisp: "должно быть лямбда-выражение" - PullRequest
9 голосов
/ 05 апреля 2010

Я только начал изучать Common Lisp несколько дней назад, и я пытаюсь создать функцию, которая вставляет число в дерево. Я получаю сообщение об ошибке,

*** - СИСТЕМА ::% EXPAND-FORM: (CONS NIL LST) должно быть лямбда-выражением

Из-за того, что вы гуглили, кажется, что это происходит, когда у вас слишком много наборов скобок, но, посмотрев на это в течение часа или около того и изменив ситуацию, я не могу понять, где я мог бы это делать. 1007 *

Это код, где это происходит:

(defun insert (lst probe)
    (cond ((null lst) (cons probe lst))
        ((equal (length lst) 1)
            (if (<= probe (first lst))
                (cons probe lst)
                (append lst (list probe))))
        ((equal (length lst) 2)
            ((cons nil lst) (append lst nil) (insertat nil lst 3)
                (cond ((<= probe (second lst)) (insert (first lst) probe))
                     ((> probe (fourth lst)) (insert (fifth lst) probe))
                     (t (insert (third lst) probe)))))))

Я почти уверен, что это происходит после ((равно (длина lst) 2), где идея состоит в том, чтобы вставить пустой список в существующий список, затем добавить пустой список в конец, а затем вставить пустой список в середину.

Ответы [ 4 ]

7 голосов
/ 05 апреля 2010

Если вы сделаете отступ в функции правильно, то увидите, что перед CONS NIL LST есть лишние скобки.

(defun insert (lst probe)
  (cond ((null lst) (cons probe lst))
        ((equal (length lst) 1)
         (if (<= probe (first lst))
             (cons probe lst)
           (append lst (list probe))))
        ((equal (length lst) 2)
         ((cons nil lst) (append lst nil) (insertat nil lst 3)
          (cond ((<= probe (second lst)) (insert (first lst) probe))
                ((> probe (fourth lst)) (insert (fifth lst) probe))
                (t (insert (third lst) probe)))))))

В большинстве IDE для Lisp вы можете использовать выражения. В LispWorks выберите все выражение и выполните m-x Indent Region.

6 голосов
/ 05 апреля 2010

Правильно! Проблема в строке сразу после этого, где написано

((cons nil lst) (append lst nil) (insertat nil lst 3) ...

Проблема в двух открывающих скобках. Круглые скобки могут изменить значение в специальных контекстах (например, форма cond, которую вы используете), но в этом контексте круглые скобки означают обычное применение функции, как вы, вероятно, привыкли. Это означает, что первая вещь после скобок должна быть функцией. С точки зрения внешних круглых скобок, первое - это (cons nil lst), так что это должна быть функция (а это не так).

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

(setq lst (cons nil lst))
(setq lst (append lst nil))
(setq lst (insertat nil lst 3))
...
2 голосов
/ 28 марта 2013

Чтобы исправить немедленную ошибку, вы можете просто добавить туда PROGN (CONS NIL ...). PROGN работает, оценивая каждую форму в нем и возвращает значение последней формы в нем в качестве значения.

Тем не менее, ваша программа по-прежнему не будет делать то, что вы думаете, она будет делать (я так думаю) Вы знаете, в Common Lisp вы используете первый объект cons для представления всего непустого списка, и вы не можете просто заменить главные cons. Лучший способ - вернуть новый список в качестве значения функции.

(defun insert (lst probe)
  (ecase (length lst)
    (0 (list probe))
    (1 (let ((c (first lst)))
         (if (<= probe c)
             (list probe c)
             (list c probe))))
    (2 (cond
         ((<= probe (first lst)) 
          (list probe (first lst) nil (second lst) nil))
         ((> probe (second lst))
          (list nil (first lst) nil (second lst) probe))
         (t
          (list nil (first lst) probe (second lst) nil))))))

Возможно, вы захотите (setf lst (insert lst [some-number])) при использовании этой функции.

1 голос
/ 05 апреля 2010

Вы правы; в строке, помеченной как «ошибка здесь», есть синтаксическая ошибка:

(defun insert (lst probe)
  (cond ((null lst) (cons probe lst))
        ((equal (length lst) 1)
         (if (<= probe (first lst))
             (cons probe lst)
             (append lst (list probe))))
        ((equal (length lst) 2)
         (#|Error is here|# (cons nil lst) (append lst nil) (insertat nil lst 3)
          (cond ((<= probe (second lst)) (insert (first lst) probe))
                ((> probe (fourth lst)) (insert (fifth lst) probe))
                (t (insert (third lst) probe)))))))

Для компилятора / интерпретатора форма читается как вызов функции для «функции» (cons nil list), которая вообще не является функцией. Компилятор жалуется здесь на использование составной формы в позиции «оператор», которая не является lambda (единственный вид составной формы, принятой в этой позиции)

((cons nil lst)                         #| <-- Form in operator position |#
 (append lst nil)                       #| <-- First argument form |#
 (insertat nil lst 3)                   #| <-- Second argument form |#
 (cond ((<= probe (second lst)) (insert (first lst) probe)) #| Third argument |#
       ((> probe (fourth lst)) (insert (fifth lst) probe))
       (t (insert (third lst) probe))))

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

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