我有一个列表“直”:
(setq straight '(
("Arad" 366)
("Bucharest" 0)
("Craiova" 160)
("Dobreta" 242)
("Eforie" 161)
("Fagaras" 176)
("Giurgiu" 77)
("Hirsova" 151)
("Iasi" 226)
("Lugoj" 244)
("Mehadia" 241)
("Neamt" 234)
("Oradea" 380)
("Pitesti" 100)
("Rimnicu Vilcea" 193)
("Sibiu" 253)
("Timisoara" 329)
("Urziceni" 80)
("Vaslui" 199)
("Zerind" 374)))
我有一个列表("Pitesti" 101)
。我试图通过“直接”搜索并找到对应于“Pitesti”的值。但是,当我运行我的功能时,终端停止响应输入命令,并且不响应我写的任何内容。这是功能:
(defun her (node)
(setq s straight)
(setq c '())
(loop while (not (eq (car node)
(caar s)))
do (setq s (cdr s)))
(setq c (append node (car (cdar s)))))
答案 0 :(得分:2)
首先,您的直接问题:eq
表示对象标识。我想你给这个函数一个城市名称的单例列表,所以当你比较(eq (car node) (caar s))
时,你比较两个字符串。只要这两个字符串不是同一个对象(如果它们都是从同一个编译中读取的文字,这可能会发生 - 这在这里似乎不太可能),这将是错误的。相反,您应该使用string=
。
由于您的比较永远不会返回true,因此该循环将继续将s
设置为straight
的尾部,但请注意cdr
的{{1}}为{{1}再次:这永远不会终止。
因此,将nil
替换为nil
可能会解决您的直接问题。但是,还有更多问题。
如果您传递的字符串在eq
中实际不存在,会发生什么?然后,它永远不会终止。这种循环的更好方法是:
string=
straight
- (loop :for pair :in straight
:when (string= (car node) (car pair))
:do (return pair))
构造将在列表的末尾终止,因此如果缺少字符串,您将返回for
。 in
有另一个构造来查找内容:nil
:
Loop
说到寻找,为什么不使用thereis
代替(loop :for pair :in straight
:thereis (when (string= (car node) (car pair)) pair))
:
find
由于使用简单关联结构的列表列表相当普遍(“关联列表”或“alist”),因此有一个专门的表单:
loop
最后,一个明显的一般性问题:你始终(find (car node) straight
:test #'string=
:key #'first)
免费(很可能是未绑定的)变量。不要那样做。努力编写引用透明的函数。用(assoc (car node) straight
:test #'string=)
等建立本地绑定。当你有结果时,只需返回它,不要为它设置一些全局变量。