質問

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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top