2012-03-15 15 views
6

Im conseguir la temida * no puede ser echado a un error IFn con una simple función matemática aquí:Clojure: Entero no puede lanzar al 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))))) 

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

Los argumentos son simplemente un montón de números:

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

Mis pensamientos/Mi pregunta

Por lo general, cuando me sale este error, me parece que se debe a

1) Un paréntesis adicional (es decir, cuando accidentalmente he puesto un cierre adicional en mi código) O

2) Argumentos que están mal ordenados (obviamente, una excepción de lanzamiento).

Mi pregunta es simplemente ... cómo solucionar este fragmento, y opcionalmente, ¿cómo puedo vencer esta excepción común de una vez? Parece que ocurre con bastante frecuencia en mis expediciones de codificación de Clojure, y estoy pensando que tal vez todavía no he conseguido el estilo de desarrollo correcto.

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

ACTUALIZACIÓN:

he plagado mi código con la sintaxis unregular. Los errores estaban en las funciones internas, que usa una llamada a funciones estilo java/c: por ejemplo, max/log ...

Respuesta

6

Me parece que tiene un problema con las llamadas log(sc1), etc.

debe mirar (suponiendo registro se define en alguna parte) algo como:

(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)))) 

Si lo que desea es utilizar el registro de Java, sustituye log con Math/log que llama a la función de registro estático en java.lang.Math

+0

considerar la aprobación de un mapa como argumentos en lugar de un millón de argumentos ordenados y utilizar el ': keys' macro desestructuración. –

14

Me parece que las expresiones ofensivas son (x32, (/ m1 min_m1)) y (x32, (/ tca_ratio min_tca)) y también las log (..).

Clojure sigue la convención de lisp estándar de tener el primer elemento de una lista sin comillas como una función para llamar. En otras palabras, desea tener (log ...) en lugar de log (...) y (max ...) en lugar de (max (...))

Encontrar estos errores es bastante fácil en su estilo particular: todo lo que coincida con "XXX (" donde XXX es un número de no-espacio, los caracteres no-paréntesis es un error

0
how can I defeat this common exception once and for all 

con el tiempo y la práctica que va a mejorar con dynamic typing

1
..

La depuración de este tipo de cosas se beneficia del uso de clojure.stacktrace o similar (puede haber mejores/mejores opciones en Clojure 1.3 que no he investigado), vea Obtain a callstack in Clojure y d http://tech.puredanger.com/2010/02/17/clojure-stack-trace-repl/.

Tenga en cuenta que *e está obligado a la excepción más reciente en la réplica.

Por ejemplo:

user=> (defn broken [x] 
     (let [internal (fn [y] (y))] 
      (internal x)))

user=> (broken 1) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0)

user=> (use 'clojure.stacktrace)

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)

Cuestiones relacionadas