Je laisse ça ici au cas où ça puisse aider quelqu'un. J'invente peut-être des choses, mais je n'ai rien trouvé de similaire.
Problème : en général, il n’est pas possible d’accéder directement aux parties d’une expression de fonction (expression entre guillemets) car il ne s’agit pas d’un type de données d’expression mais d’une fonction ; par conséquent, les fonctions habituelles de manipulation d’expressions ne fonctionnent pas.
f = Function( { x }, Return( x ) );
Show( Type( Name Expr(f) ), N Arg( Name Expr(f) ) );
// output:
Type(Name Expr(f)) = "Function";
N Arg(Name Expr(f)) = 0;
Il existe cependant une astuce : vous pouvez transformer une fonction en un type de données Expression en utilisant :
Parse( Char( Name Expr( function ) ) )
Il existe peut-être une méthode plus élégante, mais après des heures de recherche et mes propres essais, je ne l'ai pas trouvée, et même celle-ci, je l'ai découverte presque par hasard juste avant d'abandonner.
Vous pouvez ensuite accéder à ses arguments via la fonction Arg(). Elle en possède deux ou trois, selon la présence ou non d'une liste de variables locales. Le premier argument est la liste des entrées de la fonction, le deuxième est la liste des variables locales si elle est présente, et le dernier est le corps de la fonction.
f = Function( { greeting, planet }, { output },
output = Concat( greeting, " ", planet, "!");
Return( output )
);
f_as_expr = Parse( Char( Name Expr( f ) ) );
Show( Arg( f_as_expr, 1 ), Arg( f_as_expr, 2 ), Arg( f_as_expr, 3 ) )
// output:
Arg(f_as_expr, 1) = {greeting, planet};
Arg(f_as_expr, 2) = {output};
Arg(f_as_expr, 3) = output = greeting || " " || planet || "!"; Return(output);
Par exemple, j'ai une fonction d'interface utilisateur avec de nombreuses boîtes d'affichage, la plupart étant assignées à une variable. Je la mets à jour fréquemment, et la gestion de la liste des variables locales devient fastidieuse à la longue, car je préfère éviter l'utilisation de `{default local}` en raison du contrôle limité sur la portée des variables et des risques de fuite de mémoire. Je sais que je pourrais utiliser un tableau associatif ou une approche similaire, mais comme je gère également la liste des noms des boîtes d'affichage dans une liste externe pour d'autres usages, je peux l'injecter dynamiquement dans la fonction en tant que variable locale. Bien sûr, il est également possible de modifier les entrées et le corps de la fonction de la même manière.
Names Default To Here(1);
// f must be passed as Name Expr(f), add_locals as list of strings
inject_locals = Function( { f, add_locals }, { f_as_expr, cur_locals, new_locals },
f_as_expr = Parse( Char( Name Expr( f ) ) );
add_locals = Transform Each( {al}, add_locals, Parse(al) );
Match( N Arg( f_as_expr ),
2,
Insert Into( f_as_expr, add_locals, 2 ),
3,
cur_locals = Arg( f_as_expr, 2);
new_locals = cur_locals || add_locals;
Substitute Into( f_as_expr, cur_locals, new_locals ),
Throw( "inject_local error: unexpected function structure.")
);
Return( Eval( Name Expr( f_as_expr ) ) )
);
// simplified example of use
f = Function( {}, { output },
greeting = "Hello";
planet = "Earth";
output = Concat( greeting, " ", planet, "!" )
);
// globals to show that f internals remain local after injection
greeting = "Goodbye";
planet = "Mars";
additional_locals = { "greeting", "planet" };
f_injected = inject_locals( Name Expr(f), additional_locals );
Show( f, f_injected, f_injected(), greeting, planet )
// output:
f = Function({},{output},greeting = "Hello"; planet = "Earth"; output = greeting || " " || planet || "!");
f_injected = Function({},{output, greeting, planet},greeting = "Hello"; planet = "Earth"; output = greeting || " " || planet || "!");
f_injected() = "Hello Earth!";
greeting = "Goodbye";
planet = "Mars";