Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of code in Clojure

Tags:

clojure

I have a simple yet frustrating problem in Clojure, I have a function (let's call it read-function) which figures out what the user wants to do from his input then calls another function that does that (let's call it action-function). This action-function calls the read-function when it's done so the user can perform another task.

Now my problem is that if I put the code for read-function before the code for action-function, I get an error in read-function saying that it doesn't know what action-function is (because the code for it is further down) and if I do the opposite, well I get a similar error obviously, saying that read-function cannot be resolved etc.

Is there a simple way to fix this ?

The actual code:

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

like this, I get an error at the (readCmd botin) line in the ajout function saying : Unable to resolve symbol: readCmd in this context

If I put the code for these two functions in the reverse order I will get an error saying : Unable to resolve symbol: ajout in this context

like image 500
JoOb Avatar asked Jul 12 '09 20:07

JoOb


2 Answers

You can use forward declarations in Clojure so you can call functions that haven't been defined yet.

(declare readCmd) 

should work!

In Clojure, the order in which you define functions is important, a function can't call another function (or anything for that matter) that hasn't been defined yet. That's why we have forward declarations.

like image 160
Rayne Avatar answered Sep 23 '22 03:09

Rayne


As the others already answered, you need to (declare readCmd) to fix your immediate problem.

However, there are still problems with this code, because it actually implements iterative process using mutual recursion (readCmd -> ajout -> readCmd -> imprimer -> readCmd -> ...) which will consume stack and will you'll get (on) stack overflow. A better way to organize this, would be to make readCmd tail recursive, and make it call the actions. When an action returns, readCmd tail recursively calls itself.

Also this code snippet:

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

probably is not what you want to do: it'll call println and will try to use the result as a function. Use "do" instead:

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

You may also consider reading about case or cond, they will simplify the nested ifs.

Another strange thing about your code is

(def botin botin) 

what it is about?

like image 25
ivant Avatar answered Sep 21 '22 03:09

ivant