用 Clojure 重写 Land of Lisp 的向导游戏
我正在尝试重写“Land of Lisp”中的向导游戏 http://landoflisp.com/wizards_game.lisp
(def *nodes* {:living-room "you are in the living-room. a wizard is snoring loudly on the couch."
:garden "you are in a beautiful garden. there is a well in front of you."
:attic "you are in the attic. there is a giant welding torch in the corner."})
(def *edges* {:living-room '((garden west door) (attic upstairs ladder))
:garden '(living-room east door)
:attic '(living-room downstairs ladder)})
(defn describe-location [location nodes]
(nodes location))
(defn describe-path-raw [edge]
`(there is a ~(last edge) going ~(second edge) from here.))
(defn describe-path [edge]
(map #(symbol (name %)) (describe-path-raw edge)))
(defn describe-paths [location edges]
(apply concat (map describe-path-raw (location edges))))
尝试时:
(println (describe-paths :attic *edges*))
我遇到了这个异常:
线程“main”中的异常java.lang.RuntimeException:java.lang.IllegalArgumentException:不知道如何从以下位置创建ISeq:clojure.lang.Symbol(wizard-game.clj:0)
我没有 Lispy 眼睛然而,我做错了什么?
I'm trying to rewrite the Wizard game from "Land of Lisp" http://landoflisp.com/wizards_game.lisp
(def *nodes* {:living-room "you are in the living-room. a wizard is snoring loudly on the couch."
:garden "you are in a beautiful garden. there is a well in front of you."
:attic "you are in the attic. there is a giant welding torch in the corner."})
(def *edges* {:living-room '((garden west door) (attic upstairs ladder))
:garden '(living-room east door)
:attic '(living-room downstairs ladder)})
(defn describe-location [location nodes]
(nodes location))
(defn describe-path-raw [edge]
`(there is a ~(last edge) going ~(second edge) from here.))
(defn describe-path [edge]
(map #(symbol (name %)) (describe-path-raw edge)))
(defn describe-paths [location edges]
(apply concat (map describe-path-raw (location edges))))
When trying:
(println (describe-paths :attic *edges*))
I got this exception:
Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol (wizard-game.clj:0)
I don't have a Lispy eye yet, what I'm doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
将其放入 REPL 中,并运行跟踪:
此时,我将代码复制到 REPL 中。 (未显示)
接下来,我运行跟踪:
所以问题是(描述路径原始客厅)。正如错误消息指出的那样,living-room 是一个符号,该函数正在尝试执行诸如调用 last 和 secondary 之类的操作,而这只能按顺序完成。
那么为什么会发生这种情况?
在描述路径内部,您正在调用(位置边缘)。这里,位置是:阁楼,边缘是地图。因此,(位置边缘)计算为(客厅楼下的梯子)。您将describe-path-raw映射到此列表上,其结果是:
这将在第一次调用时引发异常,因为living-room是一个符号,而不是一个序列。
Putting this into a REPL, and running trace:
At this point I copy in your code into the REPL. (not shown)
Next, I run a trace:
So the problem is (describe-path-raw living-room). As the error message points out, living-room is a symbol, and this function is trying to do things like call last and second on it, which can only be done on sequences.
So why is this happening?
Inside of describe-paths, you are calling (location edges). Here, location is :attic, and edges is a map. Therefore, (location edges) works out to (living-room downstairs ladder). You are mapping describe-path-raw onto this list, which works out to:
And this is throwing an exception on the first call, since living-room is a symbol, not a sequence.
看起来
describe-paths
期望在*edges*
映射中查找的值将是列表的列表,而不仅仅是列表。请注意:living-room
条目与:garden
和:attic
条目之间的区别:前者有一个顶级脊柱,其下方您会发现两个三元组,而后两个每个只有一个三元组。函数
describe-path-raw
期望接收一个至少大小为2的元组,但它实际上只对大小为3的元组有意义;将*edges*
映射中的四个三元组中的任何一个输入给它都可以。您遇到的问题是由于将map
应用于:attic
的*edges*
条目,该条目获取列表并提供列表对象一对一到
describe-path-raw
:在这三种形式中,传递给
describe-path-raw
的参数是一个符号,而不是列表describe-path-raw
所期望的。简而言之,尝试在
*edges*
映射中的后两个值周围添加一组额外的括号,将每个列表嵌套在新的顶级列表中。It looks like
describe-paths
expects that the value looked up in the*edges*
map will be a list of lists, not just a list. Note the difference between the:living-room
entry and the:garden
and:attic
entries: the former has a top-level spine below which you find two three-tuples, whereas the latter two each have just one three-tuple.Function
describe-path-raw
expects to receive a tuple of at least size two, but it really only makes sense here for those of size three; feeding it any of the four three-tuples in the*edges*
map will work. The problem you ran into is due to applyingmap
to the*edges*
entry for:attic
, which takes the listand feeds the list objects one-by-one to
describe-path-raw
:In each of those three forms, the argument passed to
describe-path-raw
is a symbol, rather than the list expected bydescribe-path-raw
.In short, try adding an extra set of parentheses around the second two values in your
*edges*
map, nesting each list within a new top-level list.