我把这个留在这里,希望能帮到别人。也许我是在发明热水器,但我确实找不到类似的。
问题:通常情况下,无法直接访问函数“表达式”(用引号括起来)的各个部分,因为它实际上不是表达式数据类型,而是函数,因此常用的表达式操作函数不起作用:
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,取决于是否存在局部变量列表。第一个参数是函数输入列表,第二个参数是局部变量列表(如果存在),最后一个参数是函数体。
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";