Clojure: целое число не может быть приведено к IFn - PullRequest
6 голосов
/ 16 марта 2012

Я получаю страшное * не может быть приведено к ошибке IFn с помощью простой математической функции здесь:

(defn calc [sc1 m1 alpha beta gamma ta1 tb1 min_m1 min_tca tca_ratio x32]
        (* 
           (max(0,
                (+
                 (* alpha log(sc1)) 
                 (* beta log(m1)) 
                 (* gamma (/ ta1 tb1)) 
                 (- log(ta1) log(tb1)))))  

           (max(x32,(/ m1 min_m1)))

           (max(x32,(/ tca_ratio min_tca)))))

;;;;;;;;;;;;

Аргументы - это просто набор чисел:

(calc 1 2 3 4 5 1 2 3 4 5 1)

Мои мысли / Мой вопрос

Обычно, когда я получаю эту ошибку, я обнаруживаю, что это связано с

1) Дополнительные скобки (то есть, когда я случайно вставил дополнительное замыкание в свой код) ИЛИ

2) Аргументы, которые искажены (очевидно - исключение приведения).

У меня вопрос просто ... как исправить этот фрагмент и, если нужно, - как я могу победить это общее исключение раз и навсегда? Кажется, что это происходит довольно часто в моих экспедициях по кодированию в Clojure, и я думаю, что, возможно, у меня еще нет правильного стиля разработки.

-------------------------------------------- -----------

ОБНОВЛЕНИЕ:

Я искал свой код с нерегулярным синтаксисом. Ошибки были во внутренних функциях, которые использовал вызовы функций в стиле java / c: например, max / log ...

Ответы [ 4 ]

14 голосов
/ 16 марта 2012

Похоже, что оскорбительные выражения (x32, (/ m1 min_m1)) и (x32, (/ tca_ratio min_tca)), а также log (..).

Clojure следует стандартному соглашению lisp о том, что первый элемент списка без кавычек должен быть функцией для вызова. Другими словами, вы хотите иметь (log ...) вместо log (...) и (max ...) вместо (max (...))

Поймать эти ошибки довольно просто в вашем конкретном стиле: все, что соответствует «XXX (», где XXX - любое количество символов, не являющихся пробелами и скобками, является ошибкой.

6 голосов
/ 16 марта 2012

Мне кажется, что у вас проблема с вызовами log(sc1) и т. Д.

Должно выглядеть (если лог где-то определен) примерно так:

(defn calc [sc1 m1 alpha beta gamma ta1 tb1 min_m1 min_tca tca_ratio x32]
    (* 
     (max 0
          (+
           (* alpha (log sc1)) 
           (* beta (log m1)) 
           (* gamma (/ ta1 tb1)) 
           (- (log ta1) (log tb1))))  

     (max x32 (/ m1 min_m1))
     (max x32 (/ tca_ratio min_tca))))

Если вы просто хотите использовать журнал Java, замените log на Math/log, который вызывает функцию статического журнала в java.lang.Math

1 голос
/ 16 марта 2012

Отладка такого рода вещей выигрывает от использования clojure.stacktrace или аналогичных (в Clojure 1.3 могут быть улучшенные / улучшенные варианты, которые я не исследовал), см. Получение стека вызовов в Clojure и http://tech.puredanger.com/2010/02/17/clojure-stack-trace-repl/.

Обратите внимание, что *e связан с самым последним исключением в ответе.

Например: user=> (defn broken [x] (let [internal (fn [y] (y))] (internal x)))</p> <p>user=> (broken 1) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0) </p> <p>user=> (use 'clojure.stacktrace)</p> <p>user=> (print-stack-trace (root-cause *e) 2) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn at user$broken$internal__1206.invoke (NO_SOURCE_FILE:2) user$broken.invoke (NO_SOURCE_FILE:3)

0 голосов
/ 16 марта 2012
how can I defeat this common exception once and for all

Со временем и практикой вы поправитесь с dynamic typing.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...