Ich lasse das mal hier, falls es jemandem hilft. Vielleicht erfinde ich das Rad neu, aber ich konnte nichts Vergleichbares finden.
Problem: Im Allgemeinen ist es nicht möglich, direkt auf die Teile eines Funktionsausdrucks zuzugreifen (Ausdruck in Anführungszeichen), da es sich nicht um einen Ausdrucksdatentyp, sondern um eine Funktion handelt. Daher funktionieren die üblichen Funktionen zur Ausdrucksmanipulation nicht:
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;
Es gibt jedoch einen Trick: Sie können eine Funktion mithilfe folgender Methode in den Datentyp „Ausdruck“ umwandeln:
Parse( Char( Name Expr( function ) ) )
Vielleicht gibt es einen eleganteren Weg, aber nach stundenlanger Recherche und eigenen Versuchen konnte ich ihn nicht finden, und selbst diese Methode habe ich eher zufällig kurz vor dem Aufgeben entdeckt.
Anschließend können Sie mit `Arg()` auf die Argumente zugreifen. Es gibt zwei oder drei Argumente, je nachdem, ob eine Liste lokaler Variablen vorhanden ist. Das erste Argument ist die Eingabeliste der Funktion, das zweite die Liste lokaler Variablen (falls vorhanden) und das letzte der Funktionskörper.
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);
Ich habe beispielsweise eine Benutzeroberflächenfunktion mit vielen Anzeigefeldern, die größtenteils einer Variablen zugewiesen sind. Da ich diese Funktion häufig aktualisiere, wird die Pflege der lokalen Variablenliste mit der Zeit mühsam, da ich `{default local}` vermeiden möchte, um die Kontrolle über den Gültigkeitsbereich der Variablen zu reduzieren und Speicherlecks zu vermeiden. Mir ist bewusst, dass ich ein assoziatives Array oder einen ähnlichen Ansatz verwenden könnte. Da ich die Liste der Anzeigefeldnamen jedoch auch für andere Zwecke in einer externen Liste führe, kann ich sie dynamisch als lokale Variable in die Funktion einfügen. Selbstverständlich lassen sich auch die Funktionseingaben und der Funktionskörper auf ähnliche Weise anpassen.
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";