lisp 的问题和 do 构造与 itterating
problems with lisp and do construct with itterating
首先,我遇到了这个问题。我生成的代码不是遍历每个单词,而是遍历整个传递的参数。我正在使用 do 循环将信息传递到散列 table.
(defun set_isa (partOfSpeech &rest words)
(do ((wordVar words))
((null wordVar) nil)
(putp partOfSpeech word-dict wordVar)
(setf wordVar (cdr wordVar))))
有了这个,我使用跟踪得到了这个结果
(set_isa 'Verb 'Talk 'Run 'jump )
1. Trace: (SET_ISA 'VERB 'TALK 'RUN 'JUMP)
1. Trace: SET_ISA ==> NIL
NIL
当我调用散列table时,它只添加最后传递的参数
#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))))
您会找到更多关于风格的建议 here. See also the Info tab 参考集。
可运行的例子
在我们的函数中 putp
没有定义。所以我无法 运行 你的代码并查看确切的错误等。请始终提供完整的示例并清楚地描述你的期望和你得到的东西。 hash-table
的部分根本不清楚。它从何而来?它在我们的代码中是如何使用的?
做循环
查看初学者参考以了解 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 这样的动态会话语言中,这是一种非常好的方法。这是你的函数的一个版本,它使用了更传统的事物名称,还使用了传统的缩进,以及你丢失的代码的存根,使它全部 运行nable。
(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
replaces 存储在散列 table 中的任何值及其参数。所以最终在 table 中的唯一值是最后一个。所以我们需要解决这个问题,稍后我会做。
但事实上这并不是唯一的问题。
首先,您使用 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
:您可能只想在单个词上调用它。您可以通过简单地将每条尾巴的汽车传递给它来做到这一点,但正如 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
那没关系,只要你只 运行 它一次。好吧,我们可以做得更好:
- 我们可以使用更惯用的方式将新事物推送到存储在散列中的列表中table;
- 我们可以避免重复输入的事情,同时也更加地道。
像这样:
(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
以查看它们的作用。
首先,我遇到了这个问题。我生成的代码不是遍历每个单词,而是遍历整个传递的参数。我正在使用 do 循环将信息传递到散列 table.
(defun set_isa (partOfSpeech &rest words)
(do ((wordVar words))
((null wordVar) nil)
(putp partOfSpeech word-dict wordVar)
(setf wordVar (cdr wordVar))))
有了这个,我使用跟踪得到了这个结果
(set_isa 'Verb 'Talk 'Run 'jump )
1. Trace: (SET_ISA 'VERB 'TALK 'RUN 'JUMP)
1. Trace: SET_ISA ==> NIL
NIL
当我调用散列table时,它只添加最后传递的参数
#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))))
您会找到更多关于风格的建议 here. See also the Info tab 参考集。
可运行的例子
在我们的函数中 putp
没有定义。所以我无法 运行 你的代码并查看确切的错误等。请始终提供完整的示例并清楚地描述你的期望和你得到的东西。 hash-table
的部分根本不清楚。它从何而来?它在我们的代码中是如何使用的?
做循环
查看初学者参考以了解 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 这样的动态会话语言中,这是一种非常好的方法。这是你的函数的一个版本,它使用了更传统的事物名称,还使用了传统的缩进,以及你丢失的代码的存根,使它全部 运行nable。
(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
replaces 存储在散列 table 中的任何值及其参数。所以最终在 table 中的唯一值是最后一个。所以我们需要解决这个问题,稍后我会做。
但事实上这并不是唯一的问题。
首先,您使用 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
:您可能只想在单个词上调用它。您可以通过简单地将每条尾巴的汽车传递给它来做到这一点,但正如 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
那没关系,只要你只 运行 它一次。好吧,我们可以做得更好:
- 我们可以使用更惯用的方式将新事物推送到存储在散列中的列表中table;
- 我们可以避免重复输入的事情,同时也更加地道。
像这样:
(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
以查看它们的作用。