Executando uma função vinculada dinamicamente no Clojure

Gostaria de pré-armazenar várias chamadas de função em uma estrutura de dados e depois avaliar / executá-las em outra função.

Isso funciona como planejado para funções definidas no nível do espaço para nome comdefn (mesmo que a definição da função venha após minha criação da estrutura de dados), mas não funcionará com as funções definidas porlet [name (fn ouletfn dentro da função.

Aqui está meu pequeno exemplo independente:

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

Caso você esteja se perguntando sobre a minha configuração de teste, para ver o resultado dessas 6 instruções, comento / descomente específico das linhas OK / com falha e depois chamo(runit) do REPL.

Existe uma solução simples que eu poderia empreender para obtereval'dquoted chama funções para trabalhar para funções definidas dentro de outra função?

Atualizar:

Isso (com base na sugestão de danlei)faz trabalhos. Vamos ver se consigo fazer esse método funcionar na "vida real!"

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

Atualizar:

Este código está entrando na minha solução por umProblema de satisfação de restrições - Eu quero descobrirquem é o dono da zebra! Sou bastante novo no Clojure e principalmente na programação funcional, e isso tornou o exercício bastante desafiador. Estou caindo em muitos buracos, mas estou bem com isso, pois faz parte da experiência de aprendizado.

Eu costumava especificar as restrições como um monte de vetores simples, como este:

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

onde o primeiro de cada vetor especificaria o tipo de restrição. Mas isso me levou a uma implementação desajeitada de um mecanismo de despacho para essas regras, então decidi codificá-las como chamadas de função (citadas):

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

para que eu possa despachar a regra restritiva com um simpleseval. Isso parece muito mais elegante e "sincero". No entanto, cada uma dessas funções precisa acessar meus dados de domínio (chamadosvars) e esses dados continuam mudando à medida que o programa é executado. Eu não queria macular minhas regras introduzindo um argumento extra, então eu queriavars estar disponível para oevalfuncionaria via escopo dinâmico.

Aprendi agora que o escopo dinâmico pode ser feito usandobinding, mas também precisa de umdeclare.

questionAnswers(2)

yourAnswerToTheQuestion