我把這個留在這裡,希望能幫到別人。也許我是在發明熱水器,但我確實找不到類似的。
問題:通常情況下,無法直接存取函數「表達式」(用引號括起來)的各個部分,因為它實際上不是表達式資料類型,而是函數,因此常用的表達式運算函數不起作用:
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";