Ejecutar una función enlazada dinámicamente en Clojure

Me gustaría almacenar previamente un montón de llamadas a funciones en una estructura de datos y luego evaluarlas / ejecutarlas desde otra función.

Esto funciona según lo planeado para las funciones definidas a nivel de espacio de nombres condefn (aunque la definición de la función viene después de mi creación de la estructura de datos) pero no funcionará con las funciones definidas porlet [name (fn oletfn dentro de la función.

Aquí está mi pequeño ejemplo autónomo:

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

En caso de que se esté preguntando acerca de mi configuración de prueba, para ver el resultado de esas 6 declaraciones, comento / descomento específico de las líneas OK / fallidas y luego llamo(runit) de la REPL.

¿Hay alguna solución simple que pueda emprender para obtenereval'requoted llama a funciones para trabajar para funciones definidas dentro de otra función?

Actualizar:

Esto (basado en la sugerencia de danlei)hace trabajo. ¡Veamos si puedo lograr que este método funcione en la "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!
))

Actualizar:

Este código entra en mi solución para unProblema de satisfacción de restricciones - Quiero averiguarquien posee la cebra! Soy bastante nuevo en Clojure y especialmente en la programación funcional, y esto ha hecho que el ejercicio sea bastante desafiante. Estoy cayendo en muchos pozos, pero estoy de acuerdo con eso, ya que es parte de la experiencia de aprendizaje.

Solía especificar las restricciones como un conjunto de vectores simples, como este:

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

donde el primero de cada vector especificaría el tipo de restricción. Pero eso me llevó a una implementación incómoda de un mecanismo de despacho para esas reglas, así que decidí codificarlas como llamadas de función (citadas) en su lugar:

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

para poder enviar la regla de restricción con un simpleeval. Esto parece mucho más elegante y "lisp-y". Sin embargo, cada una de estas funciones necesita acceder a los datos de mi dominio (denominadovars), y estos datos siguen cambiando a medida que se ejecuta el programa. No quería manchar mis reglas introduciendo un argumento adicional, así que queríavars estar disponible para eleval'd funciona mediante el alcance dinámico.

Ahora he aprendido que el alcance dinámico se puede hacer usandobinding, pero también necesita undeclare.

Respuestas a la pregunta(2)

Su respuesta a la pregunta