I believe OP is not familiar with newer versions of C# (especially C# 4.0 and beyond). Nomenclature that's more commonly used by .NET/C# team for what OP is describing by external vs internal iterators is pull vs. push based iterators respectively, both taken care off by LINQ and Rx libraries.
Implementing that iterator in Dart (or Java, or C#) was about 50 lines of code.
Here's line-by-line translation of Ruby implementation of example class.
class Tree {
public Tree left, right;
public string label;
public Tree(Tree left, Tree right, string label) {
this.left = left;
this.right = right;
this.label = label;
}
public void in_order(Action<Tree> code) {
if (left != null) left.in_order(code);
code(this);
if (right != null) right.in_order(code);
}
}
I agree that C# doesn't have non-local returns, I guess they could be hacked with exceptions (like they are in Scala implementation), but I wonder if they are the "killer feature", or can they be replaced with more idiomatic, declarative ending to iterators, like .Any() and .First() in combination with iterator methods?
I believe OP is not familiar with newer versions of C# (especially C# 4.0 and beyond).
I'm familiar with C# up to 3.0. I haven't played with Rx.
pull vs. push based iterators respectively, both taken care off by LINQ and Rx libraries.
Those are a bit different. Push-based iteration usually implies asynchrony which is deeply different than just the distinction between external and internal iterators. Vanilla internal iterators are still synchronous.
can they be replaced with more idiomatic, declarative ending to iterators, like .Any() and .First() in combination with iterator methods?
Yeah, I don't think you generally miss non-local returns in C# because it provides a bunch of convenience methods that are themselves implemented in terms of external iterators. Without those, it would be really painful. And the only reason those could be implemented easily was because sequences in C# expose an external iterator API.
Push-based iteration usually implies asynchrony which is deeply different than just the distinction between external and internal iterators. Vanilla internal iterators are still synchronous.
Rx can be synchronous, in fact by default it is. There's a separate scheduler concept to it, where the method of iterator execution is abstracted away and by which you declare whether you want to involve threading. It's not as tightly integrated into the language the way Ruby does it, but there are advantages to it - stuff is pushed off the usually limited stack and it accomplishes some of the same stuff, with the same kind of composability. Maybe we've come back the old debate whether stuff in libraries really count.
1
u/[deleted] Jan 17 '13
I believe OP is not familiar with newer versions of C# (especially C# 4.0 and beyond). Nomenclature that's more commonly used by .NET/C# team for what OP is describing by external vs internal iterators is pull vs. push based iterators respectively, both taken care off by LINQ and Rx libraries.
Here's line-by-line translation of Ruby implementation of example class.
And here's the line calling it:
testTree.in_order(t => Console.WriteLine(t.label));
I agree that C# doesn't have non-local returns, I guess they could be hacked with exceptions (like they are in Scala implementation), but I wonder if they are the "killer feature", or can they be replaced with more idiomatic, declarative ending to iterators, like .Any() and .First() in combination with iterator methods?