2014-01-08 3 views
1

Привет, У меня есть этот школьный проект, с которым я почти закончил, поэтому мне не нужна помощь с кодом, проблема в том, что я никогда не закодированы в clojure, но для этого задания пришлось сделать попытку и уловить макрос в clojure со связанными формами, есть некоторые команды REPL, которые, как ожидается, будут давать разные ответы для присваивания для передачи ,,Код ошибки clojure: java.lang.Integer не может быть отнесен к clojure.lang.IFn

Anyways Im получает ошибку что я был googling, но ничто не является специфическим для этой проблемы, и большинство объяснений в основном нуждаются в собственном объяснении. Ничто не кажется адаптированным новичком, поэтому для меня это не делает.

(defmacro safe [bindings & code] 
(if (list? bindings) 
`(try 
    ~bindings 
    (catch Throwable except# except#)) 

(if (= (count bindings) 0) 
    `(try ~code 
    (catch Throwable except# except#)) 

    `(let ~(subvec bindings 0 2) 

    (try 
     (safe ~(subvec bindings 2) [email protected]) 
     (catch Throwable except# except#) 

     (finally 
     (. ~(bindings 0) close))))))) ;;safe 



(def divider(safe (/ 1 0))) 
(def reader (safe [s (FileReader. (java.io.File. "C:/text.txt"))] (. s read))) 

Так ошибка Im получаю

=> (def v (safe [s (FileReader. (java.io.File. "C:/text.txt"))] (. s read))) 
#'myProject.core/v 
=> v 
#<ClassCastException java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn> 

Так любезно любой, кто знает Clojure пожалуйста, дайте мне несколько советов о том, что это неправильно, все намеки Im получая то, что должно быть paranthesis missplaced, Я проверял код снова и снова, но не могу найти какие-либо ошибки и т. Д. Спасибо!

ответ

5

Использование macroexpand и друзей, чтобы помочь отлаживать

(def form (quote (safe [s (FileReader. (java.io.File. "test.txt"))] (. s read)))) 

(pprint (macroexpand form)) ;=> 
(let* 
[s (FileReader. (java.io.File. "test.txt"))] 
(try 
    (user/safe [] (. s read)) ; <--- Macro is recursive 
    (catch java.lang.Throwable except__1104__auto__ except__1104__auto__) 
    (finally (. s user/close)))) 

Macro является рекурсивным, так что это не полное расширение

(pprint (clojure.walk/macroexpand-all form)) ;=> 
(let* 
[s (new FileReader (new java.io.File "test.txt"))] 
(try 
    (try 
    ((. s read)) ; <-- Too many parenthesis! 
    (catch ... 

Вызов чтения возвращает целое число, которое в свою очередь, называют в качестве функция в рекурсивном расширении макросов.

+0

Я сейчас не на компьютере, но это выглядит неплохо! Итак, macroexpand - отладчик? И код, который вы написали, написан в REPL справа? – MRK187

+0

Это полезно при отладке, но это не отладчик. Он делает то, что он говорит, - показывает расширение макроса до его оценки. Вы можете найти поучительную версию функции 'safe-fn', макроса с' defn', а не 'defmacro', а затем отметить, что вызов' safe-fn' со всеми его аргументами, указанными отдельно, дает тот же результат, что и «макроэкземпляр-1» при цитированном макрокоманде. Да, это из сеанса REPL. –

+0

Итак, позвольте мне понять это, моя ошибка связана с дополнительной паретией? Так что все, что мне нужно сделать, это найти его и избавиться от него, и ошибка исчезнет? – MRK187

0
(FileReader. (java.io.File. "/tmp/text.txt")) 

дает вам значение первого символа в файле

cat /tmp/text.txt => abcd

(let [s (FileReader. (java.io.File. "/tmp/text.txt"))] (. s read)) => 97

же, как

(int \a)

и макрос ожидать функции. попробуйте:

(safe [s (FileReader. (java.io.File. "/tmp/text.txt"))] #(+ 6)) или (safe [s (FileReader. (java.io.File. "/tmp/text.txt"))] (fn [] (. s read)

+0

Привет, спасибо за помощь, но в предложении указывается, что команды, упомянутые выше, должны выглядеть так, если бы я его изменил, вероятно, это будет выглядеть так, как Im принимает ярлыки – MRK187

+0

Я должен сказать, что это фактически работает,! Все еще не уверен, хотя если бы я позволил использовать его таким образом. – MRK187

0

Решено!

Отсутствует Unquote нарезку в блоке третьей попытки, вызывая исключение

java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

это было вызвано из-за дополнительной paranthesis при чтении с recursivly,

MACROEXPAND отл.

(pprint (macroexpand-all form)) 
(let*[s 
    (new FileReader 
    (new File "test.txt"))] 
    (try 
    (try 
     ((.s read)) ;<= here 

бы изменить третьей попытки/улов из

(try 
    (safe ~(subvec bindings 2) [email protected]) 

к:

(try 
    (safe [email protected](subvec bindings 2) [email protected]) 

В моем понимании проблема была, что я был возвращен список с paranthesis, как (1 (2 3)), вызывающий исключение, когда чтение, незапрашивание заставляет его смотреть (1 2 3) и может быть прочитано или (в этом случае), выведенное из java в clojure.

Резервация для misspellz или вызов shit неправильное имя! :)

Большое спасибо A.Webb и patz.