clisp: невозможно найти из списка - PullRequest
1 голос
/ 17 апреля 2020

Я начал изучать LISP прошлой ночью, и в настоящее время я пишу основанную на тексте систему бронирования гостиничных номеров на общем LISP. Это строки, где я инициализировал свои списки и переменные:

(defparameter *rooms* (list 0))
(defvar counter 0)
(defvar room-num 0)

Ниже приведен фрагмент кода, где я манипулирую ими для поиска в моем списке:

(loop
(setq room-num(read))
    (if (and 
            (> counter 0)(equal t (find room-num '(*room*)))
        )
        (progn 
           (print "Room already exists:")
           (return 1)
        )
    )
(push room-num (cdr (last *rooms*)))
(setq counter (+ counter 1))
)

Приведенный выше код добавляет номер комнаты в список комнат, если он еще не существует в списке. У меня проблема с поиском номера комнаты в списке комнат.

Вот что я попробовал (извините, если код довольно неряшливый. Как я уже говорил, я начал работать с LISP только вчера):

(if (and (> counter 0)(equal  (member room-num *room*)))

Также попробовал:

(if ((if (member room-num '(rooms)) t nil))
        (print "Room already exists")
    )

Любая помощь будет оценена.

Ответы [ 2 ]

4 голосов
/ 17 апреля 2020
Кроме того,

, в дополнение к ответу @coredump, вы также можете использовать некоторые существующие общие средства для просмотра lisp, например: (с помощью макроса loop):

(loop for counter from 0
      for room = (read)
      until (find room rooms)
      collect room into rooms
      finally (progn (format t "room ~a already exists in ~a~%" room rooms)
                     (return (values rooms counter))))

или с этим (с использованием * 1005). *):

(let ((rooms))
  (do ((counter 0 (1+ counter))
       (room (read) (read)))
      ((find room rooms)
       (format t "room ~a already exists in ~a~%" room rooms)
       (values rooms counter))
    (push room rooms)))

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

3 голосов
/ 17 апреля 2020

Это объявление отлично:

(defparameter *rooms* (list 0))

Следующие не очень хороши:

(defvar counter 0)
(defvar room-num 0)

Специальные переменные, объявленные с defvar, должны именоваться с наушниками , ie. пара звездочек, как вы сделали для предыдущей переменной. При чтении кода полезно знать, что некоторые переменные являются глобальными.

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

(loop
(setq room-num(read))
    (if (and
            (> counter 0)(equal t (find room-num '(*room*)))
        )
        (progn
           (print "Room already exists:")
           (return 1)
        )
    )
(push room-num (cdr (last *rooms*)))
(setq counter (+ counter 1))
)

Форматирование нестандартное, пожалуйста, следуйте идиоматический c стиль, Вот ваш переформатированный код:

(loop
   (setq room-num (read))
   (when (and (> counter 0)
              (equal t (find room-num '(*room*))))
     (print "Room already exists:")
     (return 1))
   (push room-num (cdr (last *rooms*)))
   (setq counter (+ counter 1)))

Я заменил (if A (progn B C)) на (when A B C), что проще для чтения.

Теперь ваша проблема здесь:

 (equal t (find room-num '(*room*)))

Вы пытаетесь найти room-num в списке, который буквально содержит символ *room*, а не значение переменной с именем *room*. Это потому, что вы процитировали список: '(*room*) - это то же самое, что и (quote (*room*)), который при оценке просто возвращает форму, прочитанную читателем Lisp, то есть список из одного символа.

Вам просто нужно позвоните (member room-num *room*), чтобы проверить членство, и вам не нужно сравнивать возвращаемое значение (member ...) с t, используя (equal t ...): если тест пройден успешно, он будет ненулевым, ie. true.

Также:

(push room-num (cdr (last *rooms*)))

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

(push room *rooms*)

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

...