Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Scala have an equivalent to C# yield?

Tags:

I'm new to Scala, and from what I understand yield in Scala is not like yield in C#, it is more like select.

Does Scala have something similar to C#'s yield? C#'s yield is great because it makes writing iterators very easy.

Update: here's a pseudo code example from C# I'd like to be able to implement in Scala:

public class Graph<T> {    public IEnumerable<T> BreadthFirstIterator() {       List<T> currentLevel = new List<T>();       currentLevel.add(_root);        while ( currentLevel.count > 0 ) {          List<T> nextLevel = new List<T>();          foreach( var node in currentLevel ) {             yield return node;             nextLevel.addRange( node.Children );          }          currentLevel = nextLevel;       }    } } 

This code implements an iterative breadth first traversal of a graph, using yield, it returns an iterator, so that callers can traverse the graph using a regular for loop, e.g.:

graph.BreadthFirstIterator().foreach( n => Console.WriteLine( n ) ); 

In C#, yield is just syntactic sugar to make it easy to write an iterator (IEnumerable<T> in .Net, similar to Iterable in Java). As an iterator, its evaluated lazily.

Update II: I could be wrong here, but I think the whole point of yield in C# is so that you don't have to write a higher order function. E.g. you can write a regular for loop or use a method like select/map/filter/where instead of passing in a function which will then traverse the sequence.

E.g. graph.iterator().foreach(n => println(n)) instead of graph.iterator( n => println(n)).

This way you can chain them easily, e.g graph.iterator().map(x => x.foo).filter(y => y.bar >= 2).foreach(z => println(z)).

like image 845
Alex Black Avatar asked Oct 31 '09 22:10

Alex Black


1 Answers

The hijacking of the word yield here distracts from its usual intent: as an entry/exit marker in a coroutine. The C# BreadthFirstIterator in the example above appears to use yield in its coroutine sense; after a value is returned by yield, the next call to active BreadthFirstIterator's IEnumerable will continue with the next statement after yield.

In C#, yield is coupled to the idea of iteration rather than being a more general control flow statement, but within that limited domain its behavior is that of a coroutine. Scala's delimited continuations may allow one to define coroutines. Until then, Scala lacks such a capability, especially given its alternate meaning for yield.

like image 93
seh Avatar answered May 20 '23 02:05

seh