Clojure中的代码顺序

时间:2009-07-12 20:20:48

标签: clojure

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

现在我的问题是,如果我在动作函数的代码之前放入read-function的代码,我在read-function中得到一个错误,说它不知道什么是action-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))))))


)

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

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

4 个答案:

答案 0 :(得分:63)

您可以在Clojure中使用前向声明,这样您就可以调用尚未定义的函数。

(declare readCmd)

应该有用!

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

答案 1 :(得分:18)

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

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

此代码段也是:

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

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

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

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

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

(def botin botin)

它是什么意思?

答案 2 :(得分:11)

在代码顶部放置:

(declare readCmd)

答案 3 :(得分:2)

在Clojure google小组中有一个关于此问题的帖子提供了一些有趣的考虑因素,特别是关于如何使用声明可以绊倒生态系统中的某些工具:

thread

当然,你可以说好的工具应该适用于语言的所有结构:)

IMO,你有点习惯自下而上的风格,只是反过来阅读。这是一个不同的故事,你告诉你在哪里建立而不是分解它们。

当然,正如其他人所说,你可以用

转发声明
(declare my-function)