2009-07-12 6 views
35

У меня есть простая, но разочаровывающая проблема в Clojure, у меня есть функция (назовем ее функцией чтения), которая определяет, что пользователь хочет делать с его ввода, а затем вызывает другую функцию, которая делает это (назовем его action-function). Эта функция-действие вызывает функцию чтения, когда это делается, чтобы пользователь мог выполнить другую задачу.Порядок кода в 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 Ботин) линии в функции ajout говоря: Невозможно разрешить символ: readCmd в этом контексте

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

+0

Не могли бы вы опубликовать простой пример кода, что не работает. Это поможет устранить проблему. – seth

+1

Конечно ---- Код Start ---- (defn добавить [книга] (DEF бронирование в-функции книги) (readCmd книга-в-функции) ) (defn readCmd [книга] (println "Enter cmd") (def book-in-function book) (let [cmd (read-line)] (if (.equals cmd "add") ((println "Adding") (добавить книга-в-функции)) (Println "Не знаю")) ) ) --- Код End --- Если я кладу это так, я получаю Не удается разрешить символ : readCmd в этом контексте в строке вызова read-cmd в функции добавления Если я поместил две функции в обратном порядке, я получаю аналогичную ошибку, но для функции add в функции read-cmd – JoOb

+1

У меня есть отредактировал исходное сообщение, посмотрев, как выглядел комментарий :) – JoOb

ответ

11

в верхней части кода гОВОРЯ:

(declare readCmd) 
58

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

(declare readCmd) 

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

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

+14

Хаха, это напоминает мне C++ – wrongusername

+0

@wrongusername И компиляторы Pascal/Modula-2/Oberon однопроходные. Плюс ça change ... [Forward declare] (http://en.wikipedia.org/wiki/Forward_declaration) –

+3

Это одна из худших вещей о написании Clojure для меня. Мне нравится этот язык, но, похоже, это добавляет лишний болван. Компилятор мог просто сделать это неявно. – d11wtq

17

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

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

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

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

, вероятно, не то, что вы хотите сделать: он позвонит Println и будет пытаться использовать результат в виде функции. Используйте «делать» вместо:

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

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

Другая странная вещь о вашем коде

(def botin botin) 

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

2

Там в поток на группе Clojure Google об этом, что дает некоторые интересные соображения, в частности, о том, как использование заявляют может срабатывать некоторые инструменты в экосистеме:

thread

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

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

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

(declare my-function) 
Смежные вопросы