Переписывающая игра Wizard of Land of Lisp в Clojure - PullRequest
9 голосов
/ 19 марта 2011

Я пытаюсь переписать игру Мастера из "Страны Лиспа" 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)

У меня еще нет глаз Лиспи, что я делаю не так?

Ответы [ 2 ]

8 голосов
/ 19 марта 2011

Помещение в 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 для него, что можно сделать только для последовательностей.

Так почемуэто происходит?

Внутри описываемых путей, которые вы называете (края местоположения).Здесь местоположение: чердак, а ребра - это карта.Таким образом, (расположение краев) подходит для (гостиная вниз по лестнице).Вы отображаете в этот список description-path-raw, который работает так:

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

И это вызывает исключение при первом вызове, так как гостиная - это символ, а не последовательность.

1 голос
/ 20 марта 2011

Похоже, describe-paths ожидает, что значение, найденное на карте *edges*, будет списком списков, а не просто списком.Обратите внимание на разницу между записью :living-room и записями :garden и :attic: у первой есть позвоночник верхнего уровня, ниже которого вы найдете два трехкорпусных элемента, тогда как у последних двух есть только один трехкорпусный.

Функция describe-path-raw ожидает получить кортеж как минимум второго размера, но здесь это имеет смысл только для тех, кто имеет размер три;кормление его любым из четырех трех кортежей на карте *edges* будет работать.Проблема, с которой вы столкнулись, связана с применением map к записи *edges* для :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*, вложив каждый список в новый список верхнего уровня.

...