J'ai un groupe de fonctions numériques dans le clojure que je veux valider les arguments pour. Il existe de nombreux types d'arguments attendus par les fonctions, telles que des entiers positifs, des pourcentages, des séquences de nombres, des séquences de nombres non nuls, etc. Je peux valider les arguments à une fonction individuelle par: p>
Quelques Code LISP par Larry Hunter est un bel exemple de n ° 3. (Recherchez les Mon intuition est qu'une macro est plus appropriée en raison du contrôle de l'évaluation et du potentiel de calcul du temps compilé plutôt que de tout faire au moment de l'exécution. Mais, je n'ai pas rencontré un cas d'utilisation pour le code que j'écris qui semble l'exiger. Je me demande si cela vaut la peine d'écrire une telle macro. P>
Toute suggestion? P> variables de test code> macro.) P>
3 Réponses :
juste quelques réflexions. P>
J'ai le sentiment que cela dépend de la complexité et du nombre de validations et de la nature des fonctions. P>
Si vous faites des validations très complexes, vous devez casser vos validateurs de vos fonctions. Le raisonnement est que vous pouvez utiliser des plus simples pour construire des plus complexes. P>
Par exemple, vous écrivez: P>
Si vous faites simplement une énorme quantité de validations simples et que votre problème est la verbosité, (par exemple, vous avez 50 fonctions qui nécessitent tous des entiers non nuls), une macro a probablement plus de sens. P>
Une autre chose à considérer est que l'évaluation de la fonction est la clojure est impatiente. Vous pouvez obtenir une amélioration de la performance dans certains cas en n'ayant pas évalué certains paramètres si vous connaissez la fonction échouera, ou si certains paramètres ne sont pas nécessaires en fonction des valeurs d'autres paramètres. Par exemple. les tous? Le prédicat n'a pas besoin d'évaluer chaque valeur dans une collection. p>
Enfin, pour résoudre "les autres que tu n'as pas pensé". Clojure prend en charge une expédition générique sur une répartition functon. Cette fonction pourrait expédier au code approprié, ou des messages d'erreur basés sur un nombre de facteurs. P>
CLOJURE a déjà (sans papiers, peut-être sujets à changement) pour les pré-post-conditions sur genre de laide . P> J'écrirais probablement une macro juste pour que je puisse signaler quels tests ont échoué de manière succincte (citation et imprimez le test littéralement). Le code CL que vous avez lié à une apparence assez méchante avec cette énorme déclaration de cas. Les multimethods seraient mieux ici à mon avis. Vous pouvez lancer quelque chose comme ça ensemble assez facilement vous-même. P> fn code> s.
user> (divide 1 0)
; Evaluation aborted.
; Test failed: (not= x 0) for x = 0
; [Thrown class java.lang.Exception]
user> (divide 5 1)
; Evaluation aborted.
; Test failed: (even? x) for x = 5
; [Thrown class java.lang.Exception]
user> (divide 6 2)
3
Merci pour une autre bonne réponse. Cela fait à peu près exactement ce que je voulais faire. Il illustre également l'une des raisons pour lesquelles une macro est une meilleure solution. En pensant à la manière de désagréger l'argument de problème Si une fonction requise deux ou plusieurs caractéristiques, dites deux entiers positifs, la route macro vous permet de mettre le nom de l'argument de problème dans le message d'erreur, pas seulement de la valeur. Je ne pense pas que vous puissiez le faire avec une fonction.
Les conditions préalables et postconditions sont documentées ici ici clojure.org/special_Forms Rechercher la carte de condition.
Un cas où vous Besoin d'une macro b> serait si vous souhaitez modifier la langue pour ajouter automatiquement les tests à une fonction définie dans un bloc, comme ceci: (with-function-validators [test1 test2 test4]
(defn fun1 [arg1 arg2]
(do-stuff))
(defn fun2 [arg1 arg2]
(do-stuff))
(defn fun3 [arg1 arg2]
(do-stuff)))