如何正确地遍历符号作为创建散列 table 的键?
How do I correctly iterate through symbols as keys for creating a hash table?
简而言之:(gethash 'PARIS pandemic-hash-table) 返回 nil,尽管 'PARIS 是 table 中的一个键;这似乎与 hash-table 创建期间的符号 quoting/evaluation 在某种程度上有关,但我无法弄清楚。
我正在玩图形搜索(在棋盘游戏 Pandemic 中测试城市之间的最短路线;只是为了好玩 - 试图以比 'has the most edges' 更复杂的方式找到最佳研究实验室布置) .我正在使用散列 table 来保存路由数据(节点和边缘),并且需要输入数据作为初步数据:
(defvar *nodes* '('San-Francisco 'Chicago 'Atlanta 'Washington 'Montreal 'New-York 'Madrid 'Paris 'London 'Essen 'Milan 'St-Petersburg))
(defvar *edges* '(('Chicago 'St-Petersburg)
('San-Francisco 'Atlanta 'Montreal)
('Chicago 'Washington)
('Atlanta 'Montreal 'New-York)
('Chicago 'Washington 'New-York)
('Montreal 'Washington 'Madrid 'London)
('New-York 'London 'Paris)
('Madrid 'Essen 'London 'Milan)
('Madrid 'Essen 'London 'New-York)
('London 'Paris 'Milan 'St-Petersburg)
('Paris 'Essen)
('Essen 'Chicago)))
(defvar *pandemic-node-hash* (make-hash-table))
(loop for node in *nodes*
for edges in *edges*
do (setf (gethash node *pandemic-node-hash*) edges))
如果我查看生成的哈希 table:
CL-USER> (loop for key being the hash-keys of *pandemic-node-hash*
do (print key))
'SAN-FRANCISCO
... ;other keys removed for brevity
'PARIS
NIL
所以它使 table(边缘显示类似),但是,(gethash 'PARIS *pandemic-node-hash*)
returns nil
。如果我然后直接添加另一个 'PARIS 节点 (setf (gethash 'paris *pandemic-node-hash*) 'somevalue)
,并检查密钥,我得到:
(loop for key being the hash-keys of *pandemic-node-hash*
do (print key))
'other keys
'PARIS
PARIS
NIL
所以,问题 与初始散列 table 创建循环中符号('PARIS
和朋友)的求值有关,但我不太清楚发生了什么或如何正确地做到这一点。我猜 node
评估为 un 评估符号,将其传递给 gethash ...但什么是正确的方法?肯定不是(评估节点)?反引号列表,在符号前面用逗号? (呃)
为什么不
(dolist (node *nodes*)
(dolist (edges *edges*)
(setf (gethash node *pandemic-node-hash*) edges)))
但是你也用双引号引用了你的符号(正如其他人评论的那样)
为什么:
'(('Chicago 'St-Petersburg) ...)
什么时候应该只是这个(不要引用列表和每个符号)
'((Chicago St-Petersburg) ...)
如果您评估:*edges*
,您会看到这个
记住:'foo
是 (quote foo)
的缩写形式。这是一个包含两个元素的列表:符号 CL:QUOTE
和符号 FOO
.
(defun show-it (arg)
(print (list arg (type-of arg)))
(values))
上面是这个答案的一个较小的辅助函数。
CL-USER 37 > (show-it 'hamburg)
(HAMBURG SYMBOL)
上面显示函数看到的是符号 hamburg
而不是变量 hamburg
.
的值
不是
CL-USER 38 > (show-it '('hamburg))
(((QUOTE HAMBURG)) CONS)
上图:该函数看到一个嵌套列表,其中一个列表以 quote
作为符号。
注:((quote hamburg))
可以简写为('hamburg)
。
CL-USER 39 > (show-it (first '('hamburg)))
((QUOTE HAMBURG) CONS)
以上:如果我们得到第一个元素,我们得到带有quote
符号的列表。
更好
CL-USER 40 > (show-it '(hamburg))
((HAMBURG) CONS)
上面提供了一个包含一个符号的列表,符号 hamburg
.
CL-USER 41 > (show-it (first '(hamburg)))
(HAMBURG SYMBOL)
上面得到第一个元素,也就是符号hamburg
.
评价
确保您了解 Lisp 中的求值。 quote
阻止对整个引用表达式及其所有级别的评估。因此,在引用列表中引用内容是没有意义的。
在函数调用中传递参数时,引号用于防止对列表和符号求值。因此 quote
创建文字数据:文字符号、文字列表、文字向量等
因此引用是一种代码机制,而不是数据机制。
代码:
(first '(hamburg)) vs. (first (hamburg))
getting the first element of a literal list vs.
getting the first element of the result
of calling the function `hamburg`.
数据:
(paris hamburg berlin rome) vs. ('paris 'hamburg 'berlin 'rome)
A list of city names vs. a list of city names,
each nested in a list (quote ...)
因此:
('paris 'hamburg 'berlin 'rome)
没有意义。
简而言之:(gethash 'PARIS pandemic-hash-table) 返回 nil,尽管 'PARIS 是 table 中的一个键;这似乎与 hash-table 创建期间的符号 quoting/evaluation 在某种程度上有关,但我无法弄清楚。
我正在玩图形搜索(在棋盘游戏 Pandemic 中测试城市之间的最短路线;只是为了好玩 - 试图以比 'has the most edges' 更复杂的方式找到最佳研究实验室布置) .我正在使用散列 table 来保存路由数据(节点和边缘),并且需要输入数据作为初步数据:
(defvar *nodes* '('San-Francisco 'Chicago 'Atlanta 'Washington 'Montreal 'New-York 'Madrid 'Paris 'London 'Essen 'Milan 'St-Petersburg))
(defvar *edges* '(('Chicago 'St-Petersburg)
('San-Francisco 'Atlanta 'Montreal)
('Chicago 'Washington)
('Atlanta 'Montreal 'New-York)
('Chicago 'Washington 'New-York)
('Montreal 'Washington 'Madrid 'London)
('New-York 'London 'Paris)
('Madrid 'Essen 'London 'Milan)
('Madrid 'Essen 'London 'New-York)
('London 'Paris 'Milan 'St-Petersburg)
('Paris 'Essen)
('Essen 'Chicago)))
(defvar *pandemic-node-hash* (make-hash-table))
(loop for node in *nodes*
for edges in *edges*
do (setf (gethash node *pandemic-node-hash*) edges))
如果我查看生成的哈希 table:
CL-USER> (loop for key being the hash-keys of *pandemic-node-hash*
do (print key))
'SAN-FRANCISCO
... ;other keys removed for brevity
'PARIS
NIL
所以它使 table(边缘显示类似),但是,(gethash 'PARIS *pandemic-node-hash*)
returns nil
。如果我然后直接添加另一个 'PARIS 节点 (setf (gethash 'paris *pandemic-node-hash*) 'somevalue)
,并检查密钥,我得到:
(loop for key being the hash-keys of *pandemic-node-hash*
do (print key))
'other keys
'PARIS
PARIS
NIL
所以,问题 与初始散列 table 创建循环中符号('PARIS
和朋友)的求值有关,但我不太清楚发生了什么或如何正确地做到这一点。我猜 node
评估为 un 评估符号,将其传递给 gethash ...但什么是正确的方法?肯定不是(评估节点)?反引号列表,在符号前面用逗号? (呃)
为什么不
(dolist (node *nodes*)
(dolist (edges *edges*)
(setf (gethash node *pandemic-node-hash*) edges)))
但是你也用双引号引用了你的符号(正如其他人评论的那样)
为什么:
'(('Chicago 'St-Petersburg) ...)
什么时候应该只是这个(不要引用列表和每个符号)
'((Chicago St-Petersburg) ...)
如果您评估:*edges*
,您会看到这个记住:'foo
是 (quote foo)
的缩写形式。这是一个包含两个元素的列表:符号 CL:QUOTE
和符号 FOO
.
(defun show-it (arg)
(print (list arg (type-of arg)))
(values))
上面是这个答案的一个较小的辅助函数。
CL-USER 37 > (show-it 'hamburg)
(HAMBURG SYMBOL)
上面显示函数看到的是符号 hamburg
而不是变量 hamburg
.
不是
CL-USER 38 > (show-it '('hamburg))
(((QUOTE HAMBURG)) CONS)
上图:该函数看到一个嵌套列表,其中一个列表以 quote
作为符号。
注:((quote hamburg))
可以简写为('hamburg)
。
CL-USER 39 > (show-it (first '('hamburg)))
((QUOTE HAMBURG) CONS)
以上:如果我们得到第一个元素,我们得到带有quote
符号的列表。
更好
CL-USER 40 > (show-it '(hamburg))
((HAMBURG) CONS)
上面提供了一个包含一个符号的列表,符号 hamburg
.
CL-USER 41 > (show-it (first '(hamburg)))
(HAMBURG SYMBOL)
上面得到第一个元素,也就是符号hamburg
.
评价
确保您了解 Lisp 中的求值。 quote
阻止对整个引用表达式及其所有级别的评估。因此,在引用列表中引用内容是没有意义的。
在函数调用中传递参数时,引号用于防止对列表和符号求值。因此 quote
创建文字数据:文字符号、文字列表、文字向量等
因此引用是一种代码机制,而不是数据机制。
代码:
(first '(hamburg)) vs. (first (hamburg))
getting the first element of a literal list vs.
getting the first element of the result
of calling the function `hamburg`.
数据:
(paris hamburg berlin rome) vs. ('paris 'hamburg 'berlin 'rome)
A list of city names vs. a list of city names,
each nested in a list (quote ...)
因此:
('paris 'hamburg 'berlin 'rome)
没有意义。