des fonctions de programmation (ou des fonctions qui génèrent des fonctions)J'ai un problème où la solution que je souhaite est d'utiliser une fonction pour générer une fonction différente. Voici un exemple de jouet. Je m'attends à ce qu'il revienne [3,4,5]. cela ne fonctionne pas comme je l'espérais car apparemment l'argument passé (offset) n'est pas disponible pour la fonction anonyme qui est retournée. Je suppose qu'il existe un moyen de faire cela avec la substitution, mais je ne pouvais pas le comprendre.
funWrapper = Function({array, fun},
fun(array);
);
funFunctional = Function({offset},
Function({x},
x + offset;
);
);
funWrapper([1,2,3], funFUnctional(2));ScriptingRe: programmation de fonctions (ou fonctions générant des fonctions)J'ai fait quelques expériences: Comment utiliser Define Class et Programmation fonctionnelle à l'aide d'objets JSL
Envoyez un message si vous en avez plus sur le puzzle; à ce stade, je n'utilise pas beaucoup les classes JSL, mais elles peuvent être le meilleur moyen de faire ce que vous voulez. Les espaces de noms peuvent être équivalents, sans certaines des idées de sous-classification. L'un ou l'autre vous permettra de conditionner une fonction et des données ensemble, et de transmettre le package à une autre fonction par référence.
Re: programmation de fonctions (ou fonctions générant des fonctions)Merci de partager ces vignettes perspicaces, Craige.
Voici des solutions utilisant les deux approches. Les classes me semblent plus intuitives (et "this" est certainement plus facile à taper que namespace (expr (ns << get name))).
Testé à la fois dans JMP 14 Pro et JMP 12 Pro. Les classes ne sont pas disponibles dans JMP 12 Pro.
funOffsetAdder = Function({offset},
ns = NewNamespace();
ns:offset = offset;
ns:theMethod = EvalExpr(
Function({x},
this = namespace(expr(ns<<GETNAME></GETNAME>Re: programmation de fonctions (ou fonctions générant des fonctions)salut @Mittman ,
Je ne sais pas si c'est exactement ce que vous voulez, mais cela fonctionne pour résoudre au moins l'exemple que vous donnez dans votre message d'origine.
Names Default to Here (1);
fWrap = Function({array, offset}, fFun(array offset));
fFun = Function({x, offset}, x + offset);
fWrap([3, 4, 5, 6], 5 );Cela renverra [8, 9, 10, 11].
C'est une question intéressante à examiner. Si vous pouvez expliquer pourquoi vous auriez besoin de le faire de cette façon, je suis assez curieux.
J'espère que cela t'aides!,
DS
Re: programmation de fonctions (ou fonctions générant des fonctions)salut @DiedrichSchmidt , Merci pour la réponse. Cela ne fonctionne pas pour mon cas d'utilisation réel, cependant. Je veux pouvoir passer une fonction arbitraire (monotone) comme argument à une fonction qui trouve le zéro. C'est assez simple si je définis explicitement chaque fonction, mais j'ai rencontré des problèmes lorsque je voulais écrire une fonction pour créer une instance d'une fonction à partir d'une classe paramétrée. J'ai grandi dans R, qui n'est pas vraiment OO, mais où les règles de cadrage autorisent le code comme ce que j'avais dans le post original.
- EM
Re: programmation de fonctions (ou fonctions générant des fonctions)salut @Mittman ,
On dirait que vous essayez de résoudre les racines d'une équation (une fonction dans ce cas, pas une fonction JSL ()), est-ce correct?
Il existe une fonction JSL intégrée appelée Minimize () à laquelle vous pouvez passer votre fonction avec des points de départ pour que la fonction Minimize () commence sa routine d'optimisation. Cela peut être un chemin plus facile à parcourir que d'écrire votre propre fonction JSL () pour cela. Vous pouvez lire un article de blog à ce sujet ici .
J'espère que ça t'as aidé!,
DS
Re : programmation des fonctionnelles (ou fonctions qui génèrent des fonctions)Veuillez noter que les classes JMP14 ne sont pas entièrement fonctionnelles et que vous pourriez être brûlé si vous vous en fiez trop ; cependant, dans JMP12+, vous pouvez créer des classes (y compris l'héritage, les constructeurs, les destructeurs, etc.) avec des espaces de noms et de la méta-programmation.
Pour répondre à la question initiale de l'OP - vous pouvez atteindre votre objectif avec seulement des modifications minimales de votre script - notez simplement que la valeur de retour d'une fonction JSL est évaluée (avec l'instruction Eval ()) avant d'être renvoyée.Ainsi, si votre dernière instruction est une expression non évaluée (telle qu'une Expr( Function( _definition_ ) ), elle renverra la fonction comme prévu.Seule une petite astuce dans la deuxième fonction est nécessaire pour pouvoir appeler la fonction (l'instruction "fun = fun").
funWrapper = Function({array, fun},
fun = fun;
fun(array);
);
funFunctional = Function({offset},
Substitute(
Expr(
Function({x},
x + _offset_;
)
)
,
Expr( _offset_ ), offset
)
);
funWrapper([1,2,3], funFUnctional(2));