9

我正在尝试从“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*))

我得到了这个例外:

线程“主”java.lang.RuntimeException 中的异常:java.lang.IllegalArgumentException:不知道如何从以下位置创建 ISeq:clojure.lang.Symbol (wizard-game.clj:0)

我还没有 Lispy 的眼睛,我做错了什么?

4

2 回答 2

8

将其放入 REPL 并运行跟踪:

user> (ns foo (:use clojure.contrib.trace))
nil

此时我将您的代码复制到 REPL 中。(未显示)

接下来,我运行一个跟踪:

foo> (dotrace [describe-location describe-path-raw describe-path describe-paths]
              (describe-paths :attic *edges*))
TRACE t1662: (describe-paths :attic {:living-room ((garden west door) (attic upstairs ladder)),     :garden (living-room east door), :attic (living-room downstairs ladder)})
TRACE t1663: |    (describe-path-raw living-room)
; Evaluation aborted.
foo> 

所以问题是(描述路径原始客厅)。正如错误消息指出的那样,客厅是一个符号,并且此功能正在尝试对其执行调用 last 和 second 之类的操作,而这只能在序列上执行。

那么为什么会这样呢?

在描述路径内部,您正在调用(位置边缘)。在这里,位置是:阁楼,边缘是地图。因此,(位置边缘)适用于(客厅楼下的梯子)。您正在将 describe-path-raw 映射到此列表,其结果是:

((describe-path-raw living-room) (describe-path-raw downstairs) (describe-path-raw ladder))

这是在第一次调用时抛出异常,因为 living-room 是一个符号,而不是一个序列。

于 2011-03-19T17:16:09.067 回答
1

看起来describe-paths期望在*edges*地图中查找的值将是列表列表,而不仅仅是列表。:living-room注意entry 和:gardenand条目之间的区别:attic:前者有一个顶层脊椎,在它下面可以找到两个三元组,而后两个每个只有一个三元组。

函数describe-path-raw期望接收至少大小为 2 的元组,但它实际上只对大小为 3 的元组有意义;将地图中的四个三元组中的任何一个喂给它*edges*都可以。您遇到的问题是由于申请map条目*edges*for :attic,它采用列表

(living-room downstairs ladder)

并将列表对象一一提供给describe-path-raw

(describe-path-raw living-room)
(describe-path-raw downstairs)
(describe-path-raw ladder)

在这三种形式的每一种中,传递给的参数describe-path-raw都是一个符号,而不是预期的列表describe-path-raw

简而言之,尝试在*edges*地图中的后两个值周围添加一组额外的括号,将每个列表嵌套在一个新的顶级列表中。

于 2011-03-19T21:06:19.497 回答