lisp和do构造中存在的问题
首先,我有这个问题。我生成的代码不是遍历每个单词,而是遍历整个传递的参数。我使用do循环将信息传递到哈希表中lisp和do构造中存在的问题,lisp,common-lisp,Lisp,Common Lisp,首先,我有这个问题。我生成的代码不是遍历每个单词,而是遍历整个传递的参数。我使用do循环将信息传递到哈希表中 (defun set_isa (partOfSpeech &rest words) (do ((wordVar words)) ((null wordVar) nil) (putp partOfSpeech word-dict wordVar) (setf wordVar (cdr wordVar)))) 有了这个,我就可以用trace得到这个结果 (set_isa 'V
(defun set_isa (partOfSpeech &rest words)
(do ((wordVar words))
((null wordVar) nil)
(putp partOfSpeech word-dict wordVar)
(setf wordVar (cdr wordVar))))
有了这个,我就可以用trace得到这个结果
(set_isa 'Verb 'Talk 'Run 'jump )
1. Trace: (SET_ISA 'VERB 'TALK 'RUN 'JUMP)
1. Trace: SET_ISA ==> NIL
NIL
当我调用哈希表时,它只添加最后传递的参数
#S(HASH-TABLE :TEST FASTHASH-EQL (VERB . (JUMP)))
欢迎来到SO。我发现我们的问题有一些问题,希望我能给你一些提示 压痕 请正确缩进代码。这将导致更可读的代码,并将增加其他人可以帮助您的可能性
(defun set_isa (partOfSpeech &rest words)
"Put an understandable docstring here!"
(do ((wordVar words))
((null wordVar) nil)
(putp partOfSpeech word-dict wordVar)
(setf wordVar (cdr wordVar))))
你会发现更多关于风格的建议。有关参考的集合,请参见
可运行示例
在我们的函数中,putp
没有定义。因此,我无法运行您的代码,也无法查看要准确获取的错误,等等。请始终提供完整的示例,并清楚地描述您的期望和获得的结果。包含哈希表的部分根本不清楚。它来自哪里?它在我们的代码中是如何使用的
做循环
查看初学者参考资料,了解do
及其相关词的正确语法。如果要使用do
遍历列表,请尝试dolist
(dolist (item '(a b c d))
(print item))
使用do
您可以通过此构造实现相同的效果:
(do ((items '(a b c d) (rest items)))
((null items))
(print (first items)))
首先,我可能会觉得很难把括号弄对,但是如果你把它背后的逻辑弄对了,它会变得更容易。您不需要setf
部分,因为do
将处理它。欢迎使用。我发现我们的问题有一些问题,希望我能给你一些提示
压痕
请正确缩进代码。这将导致更可读的代码,并将增加其他人可以帮助您的可能性
(defun set_isa (partOfSpeech &rest words)
"Put an understandable docstring here!"
(do ((wordVar words))
((null wordVar) nil)
(putp partOfSpeech word-dict wordVar)
(setf wordVar (cdr wordVar))))
你会发现更多关于风格的建议。有关参考的集合,请参见
可运行示例
在我们的函数中,putp
没有定义。因此,我无法运行您的代码,也无法查看要准确获取的错误,等等。请始终提供完整的示例,并清楚地描述您的期望和获得的结果。包含哈希表的部分根本不清楚。它来自哪里?它在我们的代码中是如何使用的
做循环
查看初学者参考资料,了解do
及其相关词的正确语法。如果要使用do
遍历列表,请尝试dolist
(dolist (item '(a b c d))
(print item))
使用do
您可以通过此构造实现相同的效果:
(do ((items '(a b c d) (rest items)))
((null items))
(print (first items)))
首先,我可能会觉得很难把括号弄对,但是如果你把它背后的逻辑弄对了,它会变得更容易。您不需要setf
部分,因为do
会处理它。因此,理解这里发生的事情的方法是对代码进行注释,以便它告诉您它在做什么。这似乎是一种古老的调试方式,但在像CL这样的动态对话语言中,这是一种非常好的方法。这是一个函数的版本,它对事物使用了更为传统的名称,还使用了传统的索引,并为丢失的代码添加了存根,使其能够运行
(defvar *word-dict* nil)
(defun set-isa (part-of-speech &rest words)
(do ((wtail words))
((null wtail) nil)
(putp part-of-speech *word-dict* wtail)
(setf wtail (cdr wtail))))
(defun putp (part-of-speech dict thing)
(format *debug-io* "~&putp: ~A ~A ~A~%" part-of-speech dict thing))
现在这是可运行的,putp
将把它得到的作为参数打印出来
> (set-isa 'verb 'talk 'run 'jump )
putp: verb nil (talk run jump)
putp: verb nil (run jump)
putp: verb nil (jump)
nil
因此,即使这里没有实际存在错误的代码,这几乎肯定是putp
,您也可以找出问题所在:putp
用它的参数替换哈希表中存储的任何值。因此,表中唯一的值是最后一个。所以我们需要解决这个问题,我稍后会做
但事实上,这不是唯一的问题
首先,你用了一种非常奇怪的方式使用do
。do
的语法明确允许初始化和步进形式,因此实际上应该使用步进形式,而不是在正文中使用
(defun set-isa (part-of-speech &rest words)
(do ((wtail words (rest wtail)))
((null wtail) nil)
(putp part-of-speech *word-dict* wtail)))
其次,你在列表的所有尾部调用putp
:你可能只想在单个单词上调用它。您可以通过简单地将每个尾部的car传递给它来实现这一点,但是正如Martin Buchmann在另一个答案中指出的那样,您可以在语言中寻找一个迭代列表元素的构造。有很多这样的例子,dolist
就是其中之一:
(defun set-isa (part-of-speech &rest words)
(dolist (word words)
(putp part-of-speech *word-dict* word)))
现在呢
(set-isa 'verb 'talk 'run 'jump )
putp: verb nil talk
putp: verb nil run
putp: verb nil jump
nil
请注意,putp
的调用方式与以前的版本不兼容:现在在单词上调用它,而不是在列表的尾部
最后,让我们编写一个有效的putp
。我将首先编写一个非常简单的版本:
(defvar *word-dict* (make-hash-table))
(defun putp (part-of-speech dict thing)
(let ((entries (gethash part-of-speech dict '())))
(setf (gethash part-of-speech dict) (cons thing entries))))
这是可行的,但不是很好:
> (gethash 'verb *word-dict* '())
nil
nil
> (set-isa 'verb 'talk 'run 'jump )
nil
> (gethash 'verb *word-dict* '())
(jump run talk)
t
> (set-isa 'verb 'talk 'run 'jump )
nil
> (gethash 'verb *word-dict* '())
(jump run talk jump run talk)
t
没关系,只要你只运行一次。好吧,我们可以做得更好:
- 我们可以使用更惯用的方式将新事物推送到哈希表中存储的列表上李>
- 我们可以避免重复条目的事情,同时也更加习惯
像这样:
(defun putp (part-of-speech dict thing)
(pushnew thing (gethash part-of-speech dict)))
所以,现在:
> (gethash 'verb *word-dict* '())
nil
nil
> (set-isa 'verb 'talk 'run 'jump )
nil
> (gethash 'verb *word-dict* '())
(jump run talk)
t
> (set-isa 'verb 'talk 'run 'jump )
nil
> (gethash 'verb *word-dict* '())
(jump run talk)
这样好多了。您可以查看push
,以及pushnew
,查看它们的功能。因此,理解这里发生的事情的方法是对代码进行注释,以便它告诉您它在做什么。这似乎是一种古老的调试方式,但在像CL这样的动态对话语言中,这是一种非常好的方法。这是一个函数的版本,它对事物使用了更为传统的名称,还使用了传统的索引,并为丢失的代码添加了存根,使其能够运行
(defvar *word-dict* nil)
(defun set-isa (part-of-speech &rest words)
(do ((wtail words))
((null wtail) nil)
(putp part-of-speech *word-dict* wtail)
(setf wtail (cdr wtail))))
(defun putp (part-of-speech dict thing)
(format *debug-io* "~&putp: ~A ~A ~A~%" part-of-speech dict thing))
现在这是可运行的,putp
将把它得到的作为参数打印出来
> (set-isa 'verb 'talk 'run 'jump )
putp: verb nil (talk run jump)
putp: verb nil (run jump)
putp: verb nil (jump)
nil
因此,即使这里没有实际存在错误的代码,这几乎肯定是putp
,您也可以找出问题所在:putp
用它的参数替换哈希表中存储的任何值。因此,表中唯一的值是最后一个。所以我们需要解决这个问题,我稍后会做
但事实上,这不是唯一的问题
首先