29 votes

Ordre du code en Clojure

J'ai un problème simple mais frustrant avec Clojure. J'ai une fonction (appelons-la read-function) qui détermine ce que l'utilisateur veut faire à partir de son entrée, puis appelle une autre fonction qui le fait (appelons-la action-function). Cette fonction-action appelle la fonction-lecture lorsqu'elle a terminé, afin que l'utilisateur puisse effectuer une autre tâche.

Mon problème est que si je place le code de la fonction de lecture avant celui de la fonction d'action, j'obtiens une erreur dans la fonction de lecture disant qu'elle ne sait pas ce qu'est la fonction d'action (parce que son code est plus bas) et si je fais l'inverse, j'obtiens une erreur similaire, disant que la fonction de lecture ne peut être résolue, etc.

Existe-t-il un moyen simple de résoudre ce problème ?

Le code actuel :

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

)

comme ceci, j'obtiens une erreur à la ligne (readCmd botin) dans la fonction ajout disant : Impossible de résoudre le symbole : readCmd dans ce contexte

Si je mets le code de ces deux fonctions dans l'ordre inverse, j'obtiendrai une erreur disant : Impossible de résoudre le symbole : ajout dans ce contexte

50voto

Rayne Points 14518

Vous pouvez utiliser des déclarations forward dans Clojure afin d'appeler des fonctions qui n'ont pas encore été définies.

(declare readCmd)

devrait fonctionner !

Dans Clojure, l'ordre dans lequel vous définissez les fonctions est important, une fonction ne peut pas appeler une autre fonction (ou quoi que ce soit d'autre) qui n'a pas encore été définie. C'est la raison pour laquelle nous avons des déclarations en avant.

16voto

ivant Points 2120

Comme les autres ont déjà répondu, vous devez (déclarer readCmd) pour résoudre votre problème immédiat.

Cependant, il y a encore des problèmes avec ce code, parce qu'il implémente en fait un processus itératif utilisant une récursion mutuelle (readCmd -> ajout -> readCmd -> imprimer -> readCmd -> ...) qui consommera la pile et vous obtiendrez un (sur) débordement de pile. Une meilleure façon d'organiser cela, serait de rendre la queue de readCmd récursive, et de la faire appeler les actions. Quand une action revient, readCmd tail s'appelle récursivement.

Et aussi cet extrait de code :

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

n'est probablement pas ce que vous voulez faire : il appellera println et essaiera d'utiliser le résultat comme une fonction. Utilisez plutôt "do" :

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

Vous pouvez également envisager de vous renseigner sur case ou cond, qui simplifieront les ifs imbriqués.

Une autre chose étrange dans votre code est

(def botin botin)

de quoi s'agit-il ?

8voto

Brian Carper Points 40078

En haut de votre code, mettez :

(declare readCmd)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X