Переписать волшебную игру Land of Lisp в Clojure
-
27-10-2019 - |
Вопрос
Я пытаюсь переписать игру Wizard от "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)
У меня еще нет свободного глаза, что я делаю не так?
Решение
Поместить это в реплику, и бежать следование:
user> (ns foo (:use clojure.contrib.trace))
nil
На этом этапе я копирую в вашем коде в реплику. (не показаны)
Далее я запускаю след:
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>
Таким образом, проблема в том (Destive-Path-Raw Livel-Room). Как указывает сообщение об ошибке, гостиная является символом, и эта функция пытается делать такие вещи, как Call Last и Second, что можно сделать только на последовательностях.
Так почему это происходит?
Внутри описывающих путей вы звоните (края местоположения). Здесь местоположение: чердак, а края - карта. Следовательно, (края местоположения) работает (гостиная внизу лестницы). Вы нанесете на карту «Опишите пап-рост» в этот список, который работает:
((describe-path-raw living-room) (describe-path-raw downstairs) (describe-path-raw ladder))
И это бросает исключение на первом вызове, так как гостиная является символом, а не последовательности.
Другие советы
Это выглядит как 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*
Карта, гнездя каждый список в новом списке верхнего уровня.