список как аргумент функции в Лиспе - PullRequest
0 голосов
/ 04 октября 2018

У меня есть следующий код:

(defun TREE-CONTAINS (N TREE)
  (cond (( = (car TREE) nil) nil)
        (( = (car TREE) N) t)
         (t TREE-CONTAINS (N (cdr TREE)))
  )
)

, который принимает число N и список TREE и проверяет, существует ли N в списке TREE.довольно просто, но по какой-то причине я продолжаю получать эту ошибку, когда я вызываю свою функцию

(TREE-CONTAINS 3 '((1 2 3) 7 8))
*** - +: (1 2 3) is not a number

есть ли проблема с кодом?Я очень новичок в Лиспе, так что, возможно, я просто не вижу чего-то очень очевидного ... заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

В дополнение к принятому ответу, здесь есть альтернативный способ написания того же предиката, без cond:

(defun list-contains-p (number list)
  (and (consp list)
       (or (= number (first list))
           (list-contains-p number (rest list)))))
0 голосов
/ 04 октября 2018

Синтаксические ошибки

Ваш код содержит несколько синтаксических ошибок, помеченных как предупреждения компилятора:

CL-USER> (defun TREE-CONTAINS (N TREE)
           (cond (( = (car TREE) nil) nil)
                 (( = (car TREE) N) t)
                 (t TREE-CONTAINS (N (cdr TREE)))
            )
          )
;Compiler warnings :
;   In TREE-CONTAINS: Undeclared free variable TREE-CONTAINS
;   In TREE-CONTAINS: Undefined function N
TREE-CONTAINS

Причина заключается в том, что скобки в Common Lisp имеют значениеотличается от других языков программирования: они не используются для указания порядка применения операторов (как в 3 * (2 + 4), который отличается от 3 * 2 + 4), но являются неотъемлемой частью синтаксиса для определения различных частей«Оператор», как в cond или в приложении функции (например, (function-name arg1 arg2 ... argn)).Таким образом, синтаксическая ошибка в этом случае находится в последней строке, в которой вы должны вызвать функцию TREE-CONTAINS с аргументами N и (cdr TREE) как:

CL-USER> (defun TREE-CONTAINS (N TREE)
           (cond (( = (car TREE) nil) nil)
                 (( = (car TREE) N) t)
                 (t (TREE-CONTAINS N (cdr TREE)))
            )
          )
TREE-CONTAINS

Семантические ошибки

Если вы попробуете эту функцию, вы обнаружите ошибку:

 CL-USER> (TREE-CONTAINS 2 '(1 2 3))

 The value NIL is not of the expected type NUMBER.

Причина в том, что вы использовали = для сравнения числа ((car TREE)) сзначение nil, тогда как = можно использовать только для сравнения чисел.Используйте eq или eql вместо этого для общего случая:

CL-USER> (defun TREE-CONTAINS (N TREE)
           (cond (( eql (car TREE) nil) nil)
                 (( = (car TREE) N) t)
                 (t (TREE-CONTAINS N (cdr TREE)))
            )
          )
TREE-CONTAINS

CL-USER> (TREE-CONTAINS 2 '(1 2 3))
T

Существует также другая проблема: вы должны проверить, если список пуст, а не если первый элемент равен нулю.Другими словами, первое условие должно быть:

(cond ((eq TREE nil) nil)

или лучше:

(cond ((null TREE) nil)

Стилистические заметки

  1. Список является частным случаем дерева: если вы используете дерево терминов, программа должна быть более сложной, учитывая случаи, когда элементы могут быть подсписками.

  2. Использовать строчный идентификатор, поскольку все переведено в верхний регистр

  3. Поставьте закрывающие скобки в конце выражения, а не на новой строке.

Таким образом, ваша функция может выглядеть примерно так:

(defun list-contains (n list)
  (cond ((null list) nil)
        ((= (car list) n) t)
        (t (list-contains n (cdr list)))))

Проверка членства для дерева, а не для списка

Если, с другой стороны, вы хотите проверить дляобщее дерево, то есть список, который может содержать подсписки, как в (tree-contains 3 '((1 2 3) 7 8)), в вашей рекурсии вы должны рассмотреть случай, когда элемент списка сам является списком, а затем выполнить двойную рекурсию.Вот возможное решение:

CL-USER> (list-contains 2 '(1 (2 3) 4))

The value (2 3) is not of the expected type NUMBER.

CL-USER> (defun tree-contains (n tree)
           (cond ((null tree) nil)
                 ((listp (car tree)) (or (tree-contains n (car tree))
                                         (tree-contains n (cdr tree))))
                 ((= (car tree) n) t)
                 (t (tree-contains n (cdr tree)))))
 TREE-CONTAINS
 CL-USER> (tree-contains 2 '(1 (2 3) 4))
 T
...