Re: 関数のキーワード引数@vince_faller
クールな例。 共有していただきありがとうございます。 タイプミス修正
show(f(2, {y=14})); // 36 not 33
Re: 関数のキーワード引数@gzmorgan0
これは hamcrest から盗んだものだと思いますが、しばらく使用していて、実際にははるかに優れた方法です。 あなたはまだいくつかの悪いことをすることができますが、それは少し良くチェックします.
Names default to here(1);
f = function({x, kwargs = {}},
{DEFAULT LOCAL},
// kwargs
y = try(kwargs["y"], 2); // so the default is 2
z = try(kwargs["z"], 3); // 3
a = try(kwargs["a"], Expr(y+z)); // Expr(y+z)
r = x + y + z + eval(a);
return(r);
);
show(f(2)); // 12
show(f(2, {y=14})); // 33
show(f(2, {wrong=14})); // still 12
show(f(2, {y=3, a=Expr(y^2)})); // 17
Re: 関数のキーワード引数@gzmorgan0 kwargs リストに関する私の最大の問題は、何でも実行できることです。 たとえば、特定の関数ですべてのローカルを表示したい場合。
f = function({x, kwargs = {}},
{y = 2, z = 3, a = Expr(y + z)},
evallist(kwargs);
r = x + y + z;
return(r);
);
f(14, {print(namespace("local") << Get Contents)});
これは、暗号化されたコードのセキュリティ上の問題です。
私は実際に連想配列に物事を保持し、渡された引数が有効であることを確認するために << をデフォルトの連想配列と交差させます。
次に、キーと値のペアを関数に解析するだけなので、配列を使用してそれらを呼び出す必要はありません。
これらすべてを行うためのヘルプ機能がありますが、それによって独自の問題が発生します。そして、それは私が好きなよりも面倒です。
@ザングレッグ、私の悪い。私はこれらのことのほとんどについて、はるかに狭い視野を持っています。
Re: 関数のキーワード引数@vince_faller 、修正を加えた提案された kwargs={} ソリューションが引き続き気に入っています。IMHO Default Local は単純なスクリプトには適していますが、複雑なスクリプトには危険です。ローカル変数のリストを管理することをお勧めします。 とにかく、以下は kwargs ソリューションを変更したスクリプトですが、構文 {z,4} vs. z=4 を kwargs リストの項目として使用し、一般的なコード ブロックを必要とします。 関数は、ローカル連想配列を使用して、以下に示すコード ブロックを意味する「キーワード」値を割り当てることができますが、個々の変数の構文は、a+b の代わりに aa1[a] + のようなものになり、より面倒になります。 aa1[b] なので、この例ではリストを使用しています。
多くの変数を持つ関数があり、関数呼び出しごとにいくつかの変数のみを変更したい場合は、このアプローチを使用できます。 ここでの鍵は、
- varList にない限り、変数は変更されません。
- 変更された値はローカルです。
Names Default To Here( 1 );
//simple example
g1 = Function({kwargs={}}, {Default Local},
varList = {a,b,c,d,e,f};
valList = {1,2,3,4,5,6};
For(i=1, i<=nitems(kwargs), i++,
//each item must be a list of 2 values.
If(IsList(kwargs[i]),
Try(valList[loc(varList,kwargs[i][1])] = kwargs[i][2])
);
);
Eval( EvalExpr( Expr(varList) = Expr(valList)) ) ;
show(a,b,c,d,e,f);
);
myList = {{a,10},{y,-44},{f,20}};
g1(myList);
// [+] no variable gets changed unless it is in the variable list
// [-] varList and valList need to be defined
// [-] lines 7-13 would need to be added to each function, could be a global expression
// [-] instead of z=4 syntax, {z,4} syntax is required
//------Modification of Vince Faller script
f = function({x, kwargs={}},
{DEFAULT LOCAL},
// optional
varList = {x, y};
valList = {2,3};
For(i=1, i<=nitems(kwargs), i++,
//each item must be a list of 2 values.
If(IsList(kwargs[i]),
Try(valList[loc(varList,kwargs[i][1])] = kwargs[i][2])
);
);
Eval( EvalExpr( Expr(varList) = Expr(valList)) ) ;
print("Before Bad Call");
show(y);
print("Bad Call");
//even though f2 is default local,
//because it's not explicit in the function it writes to here
f2(1, { {b,3}, {y,5}});
print("After Bad Call");
show(y);
);
f2 = function({a, kwargs={}},
{DEFAULT LOCAL},
varList= {b,c};
valList = {2,3};
For(i=1, i<=nitems(kwargs), i++,
//each item must be a list of 2 values.
If(IsList(kwargs[i]),
Try(valList[loc(varList,kwargs[i][1])] = kwargs[i][2])
);
);
Eval( EvalExpr( Expr(varList) = Expr(valList)) ) ;
show(a, b, c);
);
f(1, {z=2});
Re: 関数のキーワード引数右。 信じられないかもしれませんが、古い JSL の動作を壊さないように努めています。:)
Re: 関数のキーワード引数ああ。そのため、誰かが (何らかの理由で) その構文を使用した場合、後で az global が必要になったときに機能しなくなります。とった。
Re: 関数のキーワード引数現在、ユーザー関数への引数が評価され、z=4 は有効な式であるため、
f(1, z=4);
z=4 を評価し、グローバル z を作成して結果を 4 にし、その結果を f の y 引数に渡します。
Re: 関数のキーワード引数なぜ新しい構文が必要になるのでしょうか?呼び出すためですか、定義するためですか?同じように定義できると思います。
関数がすでにキーワード引数を使用していない場合、現在のように位置引数がデフォルトになります。
明らかに、実装前にキーワード引数を使用することはできないため、それがスクリプトを壊すとは思いません。
関数
f = function({x, y=2, z=3},
show(x, y, z);
);
他のスクリプトを壊すことはありません。
とにかく、以前のすべてのスクリプトが位置引数を使用している場合、何も壊れないと思います。
しかし、キーワードが指定されていない場合にデフォルトで位置指定になるキーワード引数があった場合、
f(1, 2, 4);
何も壊れません(私は推測しています)。 しかし、それはただ許します
f(1, z=4);
偽の名前空間が必要な理由がわかりません(ただし、関数が内部でどのように機能するかはわかりません)。
Re: 関数のキーワード引数これには、既存のスクリプトを変更しない新しい構文が必要になります。 リストが特別なレシーバーに渡される例のようなものかもしれません。 あるいは、f(1, arg:z = 2) という偽の名前空間など、呼び出し側の新しい構文かもしれません。
Re: 関数のキーワード引数ありがとう。確かにいくつかの問題があります。 おそらく最大のものは、任意の変数を関数に注入できることであり、多くの場合、変数の衝突を引き起こします。私は注意していません。
Names default to here(1);
f = function({x, kwargs={}},
{DEFAULT LOCAL},
// optional
y = 2;
z = 3;
evallist(kwargs);
print("Before Bad Call");
show(y);
print("Bad Call");
//even though f2 is default local,
//because it's not explicit in the function it writes to here
f2(1, {b=3, y=5});
print("After Bad Call");
show(y);
);
f2 = function({a, kwargs={}},
{DEFAULT LOCAL},
b=2;
c=3;
evallist(kwargs);
show(a, b, c);
);
f(1, {z=2});
Re: 関数のキーワード引数現在の「kwargs」リストのソリューションは、暫定的なトリックです。
Re: 関数のキーワード引数について標準の Jmp 関数はどのように定義されていますか?
- そのような近い補足的な引数を受け入れますいいえ保存。
- 追加列が (...) 内の任意の位置で式 Formula(...) を受け入れるようにします。
dt << New Column( "X", Formula( row() ) );
それ以外の
f(2, {y=14})できる
f(2, y(14))
どのように見えるべきですか?
Re: 関数のキーワード引数について内部関数は JSL ではなく C++ で構築されています。 ユーザー関数 (JSL 内の) は、引数をパラメーターに変換する方法を選択する他の C++ コードによって解釈されます (関数の引数は渡される外部値であり、関数のパラメーターは値を参照する内部変数名です)。
C++ で書かれた sin(A) のような関数は次のようになります。
ExpressionPointer sin( ExpressionPointer E) {
double value = evaluateExpression( E );
double answer = sin( value );
return makeExpression( answer );
}
JSL の expr() 関数は、関数が引数を学習せずに単に返すだけで、次のようになります。
ExpressionPointer expr( ExpressionPtr E ) {
return E;
}
一見すると役に立たないように見えますが、代入演算子が次の右辺を評価できるようになります。
ex = expr( a + b );
そして、a+b の結果ではなく、式ツリーを ex に保存します。 さらに興味深い例は、head(a+b) 演算子です。
ExpressionPointer head( ExpressionPointer E ) {
return MakeExpression( E->child );
}
これはアイデアの大まかな近似です。a+b の式ツリーにはルート + があり、そのルートには 2 つの子 a と b があります。E->child はルート + を取得し、それを子のない式として返します。
JMP 開発者は、99% のユースケースを簡単に作成できるように、JSL ユーザー作成関数の複雑さを隠すことを決定しました。 私が使い慣れている言語のほとんどには、操作できる式がありません (Snobol には操作できる式があり、それが JMP の patmatch() 関数の説明になっています...) リストを使用することは、式を関数に送信するための合理的な方法です。リストは同じリストに評価されます。 関数はリストのコピーを処理しています。
関数のキーワード引数ユーザー定義関数で呼び出しの際にキーワード引数を使用できるようになれば幸いです。
Names default to here(1);
f = function({x, y=2, z=3},
show(x, y, z);
);
print("What I'd like to do");
f(1, z=2);
//I want it to be 1, 2, 2
//instead of having to do
f = function({x, kwargs={}},
{DEFAULT LOCAL},
// optional
y = 2;
z = 3;
evallist(kwargs);
show(x, y, z);
);
print("Using List");
f(1, {z=2});
誰かがそれについて言及しましたここ、しかし、8年前のことなので、もう一度取り上げることにしました。
自動化とスクリプト作成Re: 関数のキーワード引数 - ステータスが「確認済み」に変更されましたRe: 関数のキーワード引数リストを使ったトリックは非常に便利です。
実際には、変数にアクセスするためにリストを評価する必要はありません。
リストをスキャンして、for each ループまたは Extract Expr を介して正しい名前を検索できます。
Names default to here(1);
get = Function ({var}, Eval(Eval Expr(Arg(Extract Expr(kwarg, Expr(Name Expr(var)) = wild()),2))));
f = function({x, kwargs={}},
{DEFAULT LOCAL},
print(get(Expr(z)));
);
f(1, {z=2});