Question

C# has generator functions which have syntax like:

IEnumerable<int> GetNats(int max)
{
   for (int i=0; i < max; ++i)
      yield return i;
}

A feature I am interested in for my programming language (a simple object-oriented programming similar to Java, Scala, ActionScript, and C#) are generator expressions. These are essentially syntactic sugar for generator functions.

My current favorite candidate is the following syntax:

IEnumerable<int> nats = 
  witheach (i in range(0, 42)) 
     yield i * 2; 

The expression range(0, 42) is a built-in generator function.

So my question is what syntax would you prefer to see for generator expressions, in a C#/Java/Scala/ActionScript type language, and why?

Some factors that may influence responses are that like Scala and ActionScript, types in my language are declared after the type. For example:

var myVar : SomeType = initialValue;

Also anonymous functions look like this:

var myFunc = function(int x) { 
  return x + 1; 
}

Other than that the rest of my language syntax resembles Java or C#. My language has a foreach statement which is very similar to C#.

Was it helpful?

Solution

There's also Python's approach--no special syntax for generators; the presence of a "yield" statement is all it takes. Any statements that takes a block could be used, though I'd expect to find only loops used in practice:

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]

Here I'm assuming the right endpoint isn't included in a range.

To be completely honest, when I saw this in Python, I had to wonder: "at what cost?"

OTHER TIPS

Check out what F# does. You can do

seq { seq-expr }    // IEnumerable<T>, a.k.a. seq<T>
[ seq-expr ]        // list<T>
[| seq-expr |]      // array<T>

where seq-expr is a form that includes most language constructs along with 'yield'. So e.g. you can write

seq {
    for i in 0..9 do
        for j in someColl do
            if i <> j then
                yield i*j
}

The F# compiler translates this code into a state machine implementation of IEnumerable (like C# does for iterator blocks).

I like this syntax because it means e.g. you can write the exact same code you would write to "do imperative stuff now", e.g.

    for i in 0..9 do
        for j in someColl do
            if i <> j then
                printfn "%d" i*j

but wrap that code in seq{} and use 'yield' and the code becomes a lazy IEnumerable instead.

IEnumerable nats = 0...42

or for generators 

IEnumerable nats = yield 0...42
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top