Подтвердить что ты не робот

Порядок кода в Clojure

У меня есть простая, но разочаровывающая проблема в Clojure, у меня есть функция (пусть вызывается ее функция чтения), которая определяет, что пользователь хочет делать с его ввода, а затем вызывает другую функцию, которая делает это (позвольте ей позвонить действие-функция). Эта функция-действие вызывает функцию чтения, когда это делается, чтобы пользователь мог выполнить другую задачу.

Теперь моя проблема в том, что если я поместил код для функции чтения перед кодом для функции действия, я получаю сообщение об ошибке в функции чтения, говорящей, что он не знает, какая функция действия (потому что код для он еще ниже), и если я делаю обратное, я получаю аналогичную ошибку, очевидно, что функция чтения не может быть разрешена и т.д.

Есть ли простой способ исправить это?

Фактический код:

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


)

вот так, я получаю ошибку на строке (readCmd botin) в функции ajout, говорящей: Не удалось разрешить символ: readCmd в этом контексте

Если я положу код для этих двух функций в обратном порядке, я получу ошибку: Не удалось разрешить символ: ajout в этом контексте

4b9b3361

Ответ 1

Вы можете использовать форвардные объявления в Clojure, чтобы вы могли вызывать функции, которые еще не определены.

(declare readCmd)

должен работать!

В Clojure порядок, в котором вы определяете функции, важен, функция не может вызвать другую функцию (или что-то в этом отношении), которая еще не определена. Вот почему у нас есть декларации вперед.

Ответ 2

Как уже сообщали другие, вам необходимо (объявить readCmd) исправить вашу непосредственную проблему.

Однако все еще есть проблемы с этим кодом, потому что он фактически реализует итерационный процесс с использованием взаимной рекурсии (readCmd → ajout → readCmd → imprimer → readCmd → ...), которая будет потреблять стек, ll get (on) переполнение стека. Лучшим способом организовать это было бы сделать reccive readCmd хвостом и заставить его вызвать действия. Когда действие возвращается, readCmd tail рекурсивно вызывает себя.

Также этот фрагмент кода:

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

Вероятно, это не то, что вы хотите сделать: он вызовет println и попытается использовать результат как функцию. Вместо этого используйте "do":

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

Вы также можете рассмотреть возможность чтения о случае или cond, они упростят вложенные ifs.

Еще одна странная вещь о вашем коде:

(def botin botin)

что это такое?

Ответ 3

В верхней части вашего кода поставьте:

(declare readCmd)

Ответ 4

В этой группе существует цепочка из Clojure google group, которая содержит некоторые интересные соображения, в частности о том, как использование объявления может вызывать некоторые средства в экосистеме:

thread

Конечно, вы могли бы утверждать, что хорошие инструменты должны работать со всеми конструкциями языка:)

ИМО, вы как бы привыкаете к восходящему стилю и просто читаете в обратном порядке. Это немного другая история, в которой вы рассказываете, где вы строите вещи, а не разлагаете их.

И, конечно, как говорили другие, вы можете переслать объявление с помощью

(declare my-function)