Clojure中的代码顺序

JoO*_*oOb 36 clojure

我在Clojure中有一个简单而令人沮丧的问题,我有一个函数(让我们称之为读函数),它从用户的输入中找出用户想要做的事情,然后调用另一个函数(让我们称之为动作函数).此动作函数在完成后调用读取函数,以便用户可以执行另一个任务.

现在我的问题是如果我在动作函数的代码之前放入read-function的代码,我在read-function中得到一个错误,说它不知道动作函数是什么(因为它的代码是进一步的如果我做相反的事情,我明显得到一个类似的错误,说读取功能无法解决等等.

有没有一种简单的方法来解决这个问题?

实际代码:

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


)
Run Code Online (Sandbox Code Playgroud)

像这样,我在ajout函数的(readCmd botin)行中得到一个错误:在这种情况下无法解析符号:readCmd

如果我以相反的顺序放置这两个函数的代码,我将得到一个错误说:无法解析符号:在此上下文中的ajout

Ray*_*yne 64

您可以在Clojure中使用前向声明,以便可以调用尚未定义的函数.

(declare readCmd)
Run Code Online (Sandbox Code Playgroud)

应该管用!

在Clojure中,定义函数的顺序很重要,函数不能调用尚未定义的另一个函数(或任何相关的函数).这就是为什么我们有前瞻性声明.

  • 这是为我写Clojure最糟糕的事情之一.我喜欢这种语言,但似乎这会增加不必要的闪光灯.编译器可以隐式地执行此操作. (3认同)
  • Rich Hickey 关于“为什么 clojure 编译器是单通的”:https://gist.github.com/reborg/dc8b0c96c397a56668905e2767fd697f#why-clojure-compiler-is-single-pass-arent-many-possible-optimizations-lost -道路 (2认同)

iva*_*ant 18

正如其他人已经回答的那样,您需要(声明readCmd)来解决您的紧急问题.

但是,这段代码仍然存在问题,因为它实际上使用相互递归(readCmd - > ajout - > readCmd - > imprimer - > readCmd - > ...)来实现迭代过程,这将消耗堆栈并且你会得到(堆栈溢出.组织这个的更好方法是使readCmd尾递归,并使其调用动作.当一个动作返回时,readCmd tail递归调用自身.

此代码段也是:

((println "Ajout 8o") (ajout botin))
Run Code Online (Sandbox Code Playgroud)

可能不是你想要做的:它会调用println并尝试将结果用作函数.改为使用"do":

(do (println "Ajout 8o") (ajout botin))
Run Code Online (Sandbox Code Playgroud)

您也可以考虑阅读有关case或cond的内容,它们将简化嵌套ifs.

你的代码的另一个奇怪之处是

(def botin botin)
Run Code Online (Sandbox Code Playgroud)

这是什么意思?


Bri*_*per 11

在代码的顶部放置:

(declare readCmd)
Run Code Online (Sandbox Code Playgroud)