誰かの役に立つかもしれないので、ここに残しておきます。もしかしたら私が独自に開発した温水システムかもしれませんが、似たようなものは見つかりませんでした。
問題点:一般的に、関数「式」(引用符で囲まれた式)の各部分に直接アクセスすることはできません。これは、実際には式データ型ではなく関数であるため、通常の式操作関数は機能しません。
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;
しかし、コツがあります。以下の方法で関数を式データ型に変換できます。
Parse( Char( Name Expr( function ) ) )
もっと洗練された方法があるのかもしれませんが、何時間も調査し、自分で試してみたものの、見つけることができませんでした。この方法も、諦めようとしていたまさにその時、ほとんど偶然に見つけたものです。
いずれにしても、その後は Arg() を使用して引数にアクセスできます。引数は、ローカル変数リストの有無によって 2 つまたは 3 つになります。最初の式引数は関数の入力リスト、2 番目はローカル変数リスト(存在する場合)、最後の引数は関数本体です。
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);
例えば、多数の表示ボックスを持つユーザーインターフェース関数があり、それらのほとんどが変数に割り当てられているとします。この関数は頻繁に更新されるため、変数スコープの制御が難しくなり、メモリリークの可能性もあるため、{default local} は使いたくないので、ローカル変数リストの管理が面倒になってきました。連想配列などの方法を使うこともできますが、表示ボックス名のリストを他の目的で外部リストにも保持しているので、それをローカル変数として関数に動的に注入することができます。もちろん、関数の入力と本体も同様の方法で変更できます。
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";