在Clojure重写Lisp土地的向导游戏

时间:2011-03-19 16:47:43

标签: clojure jvm lisp 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的眼睛,我做错了什么?

2 个答案:

答案 0 :(得分: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> 

所以问题是(describe-path-raw living-room)。正如错误消息所指出的那样,起居室是一个符号,这个函数正在尝试做一些事情,比如呼叫最后一个和第二个,这只能在序列上完成。

那为什么会发生这种情况?

在describe-paths中,您正在调用(位置边)。这里的位置是:阁楼,边缘是地图。因此,(位置边缘)可以到达(楼下的客厅梯子)。您将describe-path-raw映射到此列表,该列表适用于:

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

这是在第一次通话时抛出异常,因为起居室是符号,而不是序列。

答案 1 :(得分:1)

看起来describe-paths期望在*edges*地图中查找的值将是列表列表,而不仅仅是列表。请注意:living-room条目与:garden:attic条目之间的差异:前者有一个顶级脊椎,低于该脊椎,您会发现两个三元组,而后两个只有一个三元组。

函数describe-path-raw期望得到一个至少大小为2的元组,但对于那些大小为3的元组来说它真的有意义;喂它*edges*地图中的四个三元组中的任何一个都可以。您遇到的问题是将map应用于*edges*的{​​{1}}条目,该条目采用了列表

: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地图的后两个值周围添加一组额外的括号,将每个列表嵌套在新的顶级列表中。