リスト生成式の構文の選択[終了]
質問
C#には、次のような構文を持つジェネレーター関数があります。
IEnumerable<int> GetNats(int max)
{
for (int i=0; i < max; ++i)
yield return i;
}
私のプログラミング言語(Java、Scala、ActionScript、C#に似たシンプルなオブジェクト指向プログラミング)で私が興味を持っている機能はジェネレータ式です。これらは基本的にジェネレーター関数の構文糖衣です。
現在のお気に入りの候補は次の構文です:
IEnumerable<int> nats =
witheach (i in range(0, 42))
yield i * 2;
式 range(0、42)
は組み込みのジェネレーター関数です。
だから私の質問は、C#/ Java / Scala / ActionScript型言語で、ジェネレーター式にどの構文を表示したいのか、そしてその理由は何ですか?
応答に影響を与える可能性のあるいくつかの要因は、ScalaやActionScriptのように、私の言語の型が型の後に宣言されることです。例:
var myVar : SomeType = initialValue;
匿名関数も次のようになります。
var myFunc = function(int x) {
return x + 1;
}
それ以外は、私の言語構文の残りの部分はJavaまたはC#に似ています。私の言語には、C#に非常によく似た foreach
ステートメントがあります。
解決
Pythonのアプローチもあります。ジェネレータ用の特別な構文はありません。 「歩留まり」の存在ステートメントはそれだけです。実際に使用されているループのみが見つかると予想されますが、ブロックを取るステートメントを使用できます。
IEnumerable<int> nats =
for (i in range(0,42))
yield i*2
String phrase = "I want to buy some cheese.";
IEnumerable<int> substrs =
for (i in 0 .. phrase.length)
for (j in i .. phrase.length+1)
yield phrase[i..j]
ここでは、正しいエンドポイントが範囲に含まれないと仮定しています。
完全に正直に言うと、これをPythonで見たときに、「コストはいくらですか?」
他のヒント
F#の機能を確認してください。できます
seq { seq-expr } // IEnumerable<T>, a.k.a. seq<T>
[ seq-expr ] // list<T>
[| seq-expr |] // array<T>
seq-exprは、「yield」とともにほとんどの言語構成要素を含むフォームです。例えばあなたは書くことができます
seq {
for i in 0..9 do
for j in someColl do
if i <> j then
yield i*j
}
F#コンパイラは、このコードをIEnumerableのステートマシン実装に変換します(C#がイテレータブロックに対して行うように)。
この構文は、たとえば「今すぐ命令的なことをする」ために書くのとまったく同じコードを書くことができます。例えば、
for i in 0..9 do
for j in someColl do
if i <> j then
printfn "%d" i*j
ただし、そのコードをseq {}でラップし、「yield」を使用すると、コードは代わりに遅延IEnumerableになります。
IEnumerable nats = 0...42 or for generators IEnumerable nats = yield 0...42