clisp:无法从列表中搜索
clisp: unable to search from a list
昨晚开始学习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")
)
如有任何帮助,我们将不胜感激。
这个声明没问题:
(defparameter *rooms* (list 0))
以下几个不太好:
(defvar counter 0)
(defvar room-num 0)
用defvar
声明的特殊变量应该用earmuffs命名,即。一对星号,就像您对前一个变量所做的那样。
阅读代码时知道某些变量是全局变量会很有帮助。
此外,您正在编写一个操纵全局状态的脚本,而不是定义一个只修改局部状态的函数。对于一个小例子,这没问题,但一个很好的练习是将这个脚本封装在一个函数中。
(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))
)
格式不规范,请遵照an idiomatic style。
这是您重新格式化的代码:
(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)))
我用(when A B C)
替换了(if A (progn B C))
,这样更易读。
现在,你的问题在这里:
(equal t (find room-num '(*room*)))
您正试图在 列表中查找 room-num
,该列表字面上包含符号 *room*
,而不是名为 [=21 的变量的值=].
这是因为你引用了列表:'(*room*)
与 (quote (*room*))
相同,当评估时 return Lisp reader 读取的形式,即一个列表符号。
你只需要调用(member room-num *room*)
来测试成员资格,你不必比较(member ...)
和t
的return值,使用(equal t ...)
:如果测试成功,它将是非空的,即。是的。
还有:
(push room-num (cdr (last *rooms*)))
你不需要将房间作为最后一个元素推入,只需将其放在前面:
(push room *rooms*)
顺序在您的情况下无关紧要,并且您可以使用 last
.
避免遍历列表。
此外,除了@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))))
或这个(使用do
):
(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)))
虽然这不是答案,但使用高级工具解决问题可以节省大量调试时间。
昨晚开始学习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")
)
如有任何帮助,我们将不胜感激。
这个声明没问题:
(defparameter *rooms* (list 0))
以下几个不太好:
(defvar counter 0)
(defvar room-num 0)
用defvar
声明的特殊变量应该用earmuffs命名,即。一对星号,就像您对前一个变量所做的那样。
阅读代码时知道某些变量是全局变量会很有帮助。
此外,您正在编写一个操纵全局状态的脚本,而不是定义一个只修改局部状态的函数。对于一个小例子,这没问题,但一个很好的练习是将这个脚本封装在一个函数中。
(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))
)
格式不规范,请遵照an idiomatic style。 这是您重新格式化的代码:
(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)))
我用(when A B C)
替换了(if A (progn B C))
,这样更易读。
现在,你的问题在这里:
(equal t (find room-num '(*room*)))
您正试图在 列表中查找 room-num
,该列表字面上包含符号 *room*
,而不是名为 [=21 的变量的值=].
这是因为你引用了列表:'(*room*)
与 (quote (*room*))
相同,当评估时 return Lisp reader 读取的形式,即一个列表符号。
你只需要调用(member room-num *room*)
来测试成员资格,你不必比较(member ...)
和t
的return值,使用(equal t ...)
:如果测试成功,它将是非空的,即。是的。
还有:
(push room-num (cdr (last *rooms*)))
你不需要将房间作为最后一个元素推入,只需将其放在前面:
(push room *rooms*)
顺序在您的情况下无关紧要,并且您可以使用 last
.
此外,除了@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))))
或这个(使用do
):
(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)))
虽然这不是答案,但使用高级工具解决问题可以节省大量调试时间。