4

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#。我的语言有一个foreach与 C# 非常相似的语句。

4

3 回答 3

3

还有Python 的方法——生成器没有特殊的语法;“yield”声明的存在就是它所需要的。可以使用任何带块的语句,但我希望只找到在实践中使用的循环:

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 中看到这一点时,我不得不怀疑:“代价是什么?”

于 2009-10-24T14:31:20.333 回答
2

看看 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。

于 2009-10-24T19:34:58.140 回答
1
IEnumerable nats = 0...42

或用于发电机

IEnumerable nats = 产量 0...42
于 2009-10-24T14:14:36.403 回答