Выполнение динамически связанной функции в Clojure

Я хотел бы предварительно сохранить несколько вызовов функций в структуре данных, а затем оценить / выполнить их из другой функции.

Это работает как запланировано для функций, определенных на уровне пространства имен сdefn (хотя определение функции приходит после того, как я создал структуру данных), но не будет работать с функциями, определеннымиlet [name (fn или жеletfn внутри функции.

Вот мой маленький автономный пример:

(def todoA '(funcA))
(def todoB '(funcB))
(def todoC '(funcC))
(def todoD '(funcD)) ; unused

(defn funcA [] (println "hello funcA!"))

(declare funcB funcC)

(defn runit []
    (let [funcB (fn [] (println "hello funcB"))]
    (letfn [(funcC [] (println "hello funcC!"))]
        (funcA)       ; OK
        (eval todoA)  ; OK
        (funcB)       ; OK
        (eval todoB)  ; "Unable to resolve symbol: funcB in this context" at line 2
        (funcC)       ; OK
        (eval todoC)  ; "Unable to resolve symbol: funcC in this context" at line 3
)))

В случае, если вам интересна моя настройка теста, чтобы увидеть результат этих 6 операторов, я комментирую / раскомментирую специфические строки OK / failing, а затем вызываю(runit) из репл.

Есть ли простое исправление, которое я мог предпринять, чтобы получитьevalquoted вызовы функций для работы для функций, определенных внутри другой функции?

Обновить:

Это (по предложению Данлея)делает Работа. Посмотрим, смогу ли я заставить этот метод работать в «реальной жизни»!

(def todoB '(funcB))
(declare funcB)

(defn runit []
  (binding [funcB (fn [] (println "hello funcB"))]
    (funcB)
    (eval todoB)  ; "Unable to resolve symbol: funcB in this context" at line 1!
))

Обновить:

Этот код входит в мое решение дляПроблема удовлетворения ограничений - Я хочу узнатькто владеет зеброй! Я довольно новичок в Clojure и особенно в функциональном программировании, и это сделало упражнение довольно сложным. Я падаю во многие ямы, но я в порядке с этим, так как это часть опыта обучения.

Я использовал для определения ограничений в виде набора простых векторов, например так:

[:con-eq :spain :dog]
[:abs-pos :norway 1]
[:con-eq :kools :yellow]
[:next-to :chesterfields :fox]

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

'(coloc :japan :parliament) ; 10
'(coloc :coffee :green) ; 12
'(next-to :chesterfield :fox) ; 5

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

Теперь я узнал, что динамическое определение объема может быть сделано с помощьюbinding, но это также нуждается вdeclare.

Ответы на вопрос(2)

Ваш ответ на вопрос