Je voudrais appels pré-enregistrer un groupe de fonction dans une structure de données, puis évaluer/les exécuter à partir d'une autre fonction.L'exécution d'une fonction dynamique lié à Clojure
Cela fonctionne comme prévu pour les fonctions définies au niveau de l'espace de noms avec defn
(même si la définition de la fonction vient après ma création de la structure de données), mais ne fonctionnera pas avec les fonctions définies par let [name (fn
ou letfn
dans la fonction.
Voici mon petit exemple autonome:
(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
)))
Si vous vous interrogez sur ma configuration de test, pour voir le résultat de ces 6 déclarations I commentaire/spécifique uncomment du OK/lignes défaillantes et puis appelez (runit)
depuis le REPL.
Y at-il une solution simple que je pourrais entreprendre pour obtenir eval
'd quote
d appels à des fonctions pour travailler pour des fonctions définies dans une autre fonction?
Mise à jour:
Ce (basé sur la suggestion de Danlei) -t travail. Voyons voir si je peux obtenir cette méthode de travail dans la «vraie vie!
(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!
))
Mise à jour:
Ce code va dans ma solution pour une Constraint Satisfaction Problem - Je veux savoir who owns the zebra! Je suis assez nouveau à Clojure et surtout à la programmation fonctionnelle, et cela a rendu l'exercice assez difficile. Je tombe dans beaucoup de puits, mais je suis d'accord avec cela car cela fait partie de l'expérience d'apprentissage.
J'utilisé pour spécifier les contraintes comme un tas de vecteurs simples, comme ceci:
[:con-eq :spain :dog]
[:abs-pos :norway 1]
[:con-eq :kools :yellow]
[:next-to :chesterfields :fox]
où le premier de chaque vecteur spécifier le type de contrainte. Mais cela m'a conduit à une mise en œuvre maladroite d'un mécanisme de répartition de ces règles, alors j'ai décidé de les coder en fonction (entre guillemets) appelle à la place:
'(coloc :japan :parliament) ; 10
'(coloc :coffee :green) ; 12
'(next-to :chesterfield :fox) ; 5
donc je peux envoyer la règle contraignante avec un eval
simple. Cela semble beaucoup plus élégant et "lisp-y". Cependant, chacune de ces fonctions doit accéder à mes données de domaine (nommées vars
) et ces données changent constamment au cours de l'exécution du programme. Je ne voulais pas ternir mes règles en introduisant un argument supplémentaire, donc je voulais que vars
soit disponible pour les fonctions eval
'd via la portée dynamique.
J'ai maintenant appris que la portée dynamique peut être faite en utilisant binding
, mais il faut aussi declare
.
Êtes-vous simplement avoir les pneus ou vraiment essayer de mettre en œuvre quelque chose? Si c'est le cas, j'aimerais savoir ce que vous essayez de faire qui vous a forcé à utiliser un tel design - à première vue, des retards ou de simples fermetures pourraient faire l'affaire. – cgrand
@cgrand: Merci pour votre intérêt! J'ai ajouté une deuxième mise à jour pour expliquer ce que j'essaie de faire. Cela travaille en ce moment pour moi mais je suis ouvert à de meilleures suggestions! –
@cgrand: Mon message [Problème de satisfaction de contrainte] (http://stackoverflow.com/questions/2500504/constraint-satisfaction-problem) a maintenant ma solution complète. Si vous êtes intéressé, vous pouvez voir "binding" en action là-bas. Je suis très ouvert à la critique constructive sur mon approche amateur. –