2009-07-12 9 views
35

Tengo un problema simple pero frustrante en Clojure, tengo una función (llamémosla función de lectura) que determina lo que el usuario quiere hacer desde su entrada y luego llama a otra función que hace eso (llamémoslo acción-función). Esta función de acción llama a la función de lectura cuando está lista para que el usuario pueda realizar otra tarea.Orden del código en Clojure

Ahora mi problema es que si pongo el código para la función de lectura antes del código de acción-función, aparece un error en la función de lectura que dice que no sabe qué función-acción es (porque el código porque está más abajo) y si hago lo contrario, bueno, obviamente recibo un error similar, diciendo que la función de lectura no se puede resolver, etc.

¿Hay una manera simple de solucionar esto?

El código real:

(defn ajout [botin] 
    (def botin botin) 
    (readCmd botin) 
) 

(defn readCmd [botin] 
    (println "Entrez une commande svp ") 
    (def botin botin) 
    (let [cmd (read-line)] 
    (if (.equals cmd "a") ((println "Ajout 8o") (ajout botin)) 
     (if (.equals cmd "e") ((println "Elim 8o") (eliminer botin)) 
     (if (.equals cmd "i") ((println "Imprim 8o") (imprimer botin)) 
      ((println "Commande invalide, nous vous rapellons que les commandes possibles sont : ") (print-les-cmd) (readCmd)))))) 


) 

como este, me sale un error en el (readCmd botin) línea en la función ajout diciendo: No se puede resolver símbolo: readCmd en este contexto

Si Pongo el código para estas dos funciones en orden inverso Obtendré un error diciendo: No se puede resolver el símbolo: ajout en este contexto

+0

Podría publicar un ejemplo de código sencillo de lo que no funciona. Eso ayudaría a rastrear el problema. – seth

+1

Por supuesto ---- ---- Código de inicio (defn añadir [libro] (def reservar-en-libro función) (readCmd libro-en-función) ) (defn readCmd [libro] (println "Enter cmd") (def reservar-en-libro función) (dejar que [cmd (leer línea)] (si (.equals cMD "añadir") ((println "Adición") (añada libro-en-función)) (println "No saber")) ) ) --- --- Código final Si lo pongo de esta manera, consigo No se puede resolver símbolo : readCmd en este contexto en la línea de la llamada read-cmd en la función add Si pongo las dos funciones en el orden inverso obtengo un error similar pero para la función add en la función read-cmd – JoOb

+1

tengo editó la publicación original después de ver cómo se veía el comentario :) – JoOb

Respuesta

11

En la parte superior de su código ponga:

(declare readCmd) 
58

Puede usar las declaraciones de reenvío en Clojure para poder llamar a las funciones que aún no se han definido.

(declare readCmd) 

debería funcionar!

En Clojure, el orden en que se definen las funciones es importante, una función no puede llamar a otra función (o cualquier cosa para el caso) que aún no se haya definido. Es por eso que tenemos declaraciones avanzadas.

+14

Jaja, esto me recuerda a C++ – wrongusername

+0

@wrongusername Y los compiladores Pascal/Modula-2/Oberon single-pass. Además ça change ... [Declaración de reenvío] (http://en.wikipedia.org/wiki/Forward_declaration) –

+3

Esta es una de las peores cosas de escribir Clojure para mí. Me encanta el lenguaje, pero parece que esto agrega un bolilerplate innecesario. El compilador podría hacer esto implícitamente. – d11wtq

17

Como los demás ya respondieron, necesita (declarar readCmd) para solucionar su problema inmediato.

Sin embargo, todavía hay problemas con este código, ya que en realidad implementa un proceso iterativo utilizando la recursión mutua (readCmd -> ajout -> readCmd -> imprimer -> readCmd -> ...) que consumirá la pila y lo hará Obtendré (en) desbordamiento de pila. Una mejor forma de organizar esto sería hacer que readCmd sea recursivo y hacer que llame a las acciones. Cuando una acción retorna, readCmd tail recursivamente se llama a sí mismo.

también este fragmento de código:

((println "Ajout 8o") (ajout botin)) 

probablemente no es lo que quiere hacer: se llamará println y tratará de utilizar el resultado como una función. Utiliza "haces" en su lugar:

(do (println "Ajout 8o") (ajout botin)) 

También puede considerar leer sobre casos o cond, se simplificarán los ifs anidados.

Otra cosa extraña sobre su código es

(def botin botin) 

de qué se trata?

2

Hay un hilo en el grupo de Clojure Google acerca de esto que ofrece algunas consideraciones interesantes, en particular sobre cómo el uso de declarar puede tropezar con algunas herramientas en el ecosistema:

thread

Por supuesto, podría argumentar que las buenas herramientas deberían funcionar con todas las construcciones del lenguaje :)

IMO, te acostumbras al estilo ascendente y acabas de leer al revés. Es una historia un poco diferente tu historia donde construyes cosas en lugar de descomponerlas.

Y, por supuesto, como otros han dicho, puede reenviar declarar con

(declare my-function) 
Cuestiones relacionadas