July 27, 2012
On Friday, 27 July 2012 at 19:18:11 UTC, Artur Skawina wrote:
>
> A more or less direct translation of your original example would be:
>
> [...interesting code elided...]

Hmm. I think I need to learn more about ranges. They look quite powerful. It could, as you suggest, be nothing more than [a] a difference of syntax and [b] my ignorance of ranges. Unfortunately, I understand that information is quite scarce on the subject.
July 27, 2012
On Friday, July 27, 2012 21:22:47 Stuart wrote:
> On Friday, 27 July 2012 at 19:17:10 UTC, H. S. Teoh wrote:
> > Nevertheless, D has gotten to the point where it's powerful enough that most feature requests can be implemented in a library rather than as a language extension.
> 
> How could Yield be implemented as a library feature? Something like:
> 
>     return ITERATOR(
>        { ...setup code ... },
>        { ...loop body code... })
> 
> ?
> 
> I don't see how that would work. Variables declared in the setup would not be accessible from the body. I guess it could be done a bit like this:
> 
>     Enumerable!int ExampleFunction() {
>        ... create some variables ...
>        return ITERATOR!int( {
>           ...do something with variables...
>           ...return something...
>        } )
>     }
> 
> That the kind of thing you mean?

As they're delegates, you could just put any variables you need in both functions in surrounding function. So, something like that could be done, though it would probably be built around the idea that you'd be giving lambdas for empty, front, and popFront rather than an iterator.

But regardless, I'm sure that a library solution could be found, and at this point, unless a library solution really just doesn't work or is really ugly and the feature is really needed, it's not going to be added to the language. D is incredibly powerful, and there's been a large push (especially from Andrei) to use that power to solve problems rather than add more to the language to do it.

- Jonathan M Davis
July 27, 2012
On Friday, 27 July 2012 at 19:12:41 UTC, H. S. Teoh wrote:
>
> an implicit context-switch between two fibers

I've just looked up "fiber" and "coroutine". Sounds like a very useful concept. As previously stated, VB.NET iterators implement coroutines WITHOUT fibers; but I can see where fibers would be useful.

What is the recommended way to implement coroutines in D? More RANGE stuff?
July 27, 2012
On Fri, 27 Jul 2012 11:05:21 -0400
Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> 
> I think it's fair to say yield makes some things easier to do than ranges, and ranges makes some other things easier to do than yield. Of course, ideally you'd have both, but for the time being we don't have yield.
> 

We have this, which is essentially the same, just not quite as nice
syntax ("mixin(yield("blah"));" instead of "yield blah;")

http://forum.dlang.org/thread/jno6o5$qtb$1@digitalmars.com#post-ojeetpvwvzltxwlgphpb:40forum.dlang.org

July 27, 2012
On Fri, 27 Jul 2012 20:52:37 +0200
"Stuart" <stugol@gmx.com> wrote:

> On Friday, 27 July 2012 at 15:42:27 UTC, Sean Kelly wrote:
> > On Jul 27, 2012, at 8:05 AM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> >
> > core.thread.Fiber has yield and has been used as the basis for this style of iterator.  See Mikola Lysenko's talk from the D conference a few years ago.
> 
> I think perhaps you are confusing two different meanings of yield. I am not talking about threading. The VB.NET "yield" and "iterator" keywords can be used just as well in a single-threaded application.
> 

Fibers don't use any threads.

July 27, 2012
On Fri, 27 Jul 2012 20:47:32 +0200
"Stuart" <stugol@gmx.com> wrote:
> 
> Unless ranges (which I admit to knowing very little about) can do this, I respectfully request that Yield be supported in D.
> 

Being able to easily do things lazily is one of the main points of ranges.

July 27, 2012
On Friday, 27 July 2012 at 18:47:34 UTC, Stuart wrote:
[snip]
>
> Ah, but that depends upon the pre-existence of the dirEntries() function. I think perhaps you're missing the point - which is that "Yield" allows you to WRITE a function synchronously which will then be executed lazily, as an iterator. What you have demonstrated there is USING a lazy function. How would I write, in D, a function that would lazily assemble some data and return it as a lazy collection? I mean, without calling existing lazy functions.

Short answer: you'd implement an InputRange, just as dirEntries is
implemented.

When I started learning D, the lack of first-class coroutines ("things
that yield") struck me as a real drawback. I had grown very used to
them in Python and in Scheme.

So I learned how to write ranges. I did not totally fall in love with
them. I agree with you that there is a conceptual elegance in writing
a coroutine as if it were a regular function, just one that happens to
include a "yield" keyword that seems to "remember its place" between
calls. I'd like to see language-level support for them in D some day.

Having said that, I'm satisfied with ranges. I've seen the fiber and
opApply ways of implementing yield, and they are okay. But the fact
is, it's usually not that hard to write an input range. Just make a
struct that implements these operations:

http://dlang.org/phobos/std_range.html#isInputRange

Decide what state you need to maintain between calls; determine
meaningful definitions for empty, front, and popFront that read and
manipulate that state.

Write a few of those, and the idiom will become natural to you.

It will feel inside-out with respect to C# enumerators. But it's not
inherently bad -- certainly not bad enough to dismiss without deeper
study, and certainly not bad enough to immediately jump to fibers or
an opApply-with-mixin trick before you've at least attempted a
range-based solution.

There is a load of reusable library code in D that can be brought to
bear on ranges. It's well worth a bit of mental rewiring to benefit
from that.

Best,
Graham

July 27, 2012
On Fri, 27 Jul 2012 21:31:08 +0200
"Stuart" <stugol@gmx.com> wrote:

> On Friday, 27 July 2012 at 19:12:41 UTC, H. S. Teoh wrote:
> >
> > an implicit context-switch between two fibers
> 
> I've just looked up "fiber" and "coroutine". Sounds like a very useful concept. As previously stated, VB.NET iterators implement coroutines WITHOUT fibers; but I can see where fibers would be useful.
> 
> What is the recommended way to implement coroutines in D? More RANGE stuff?

In D, coroutines are implemented by using Fiber: http://dlang.org/phobos/core_thread.html#Fiber

July 27, 2012
On Fri, 27 Jul 2012 21:17:10 +0200
"Stuart" <stugol@gmx.com> wrote:

> On Friday, 27 July 2012 at 19:12:41 UTC, H. S. Teoh wrote:
> >
> > I'm pretty sure Yield has a performance hit as well, 'cos it amounts to an implicit context-switch between two fibers.
> 

Someone linked to an article which explained that .NET coroutines work, not by using fibers, but by translating the coroutine's source code into an equivalent switch-driven state machine. Pretty cool, actually.

> Unless I'm sorely mistaken, Yield has bugger-all to do with fibers. I say again: I'm not talking about threading.

Fibers aren't threading.

July 27, 2012
On Fri, 27 Jul 2012 17:52:27 +0200
"Jesse Phillips" <Jessekphillips+D@gmail.com> wrote:

> so I guess you can take my opinion of GUI designers with an atom of salt.

<annoyingly pedantic>It would have to be a molecule. Try to take an
atom of salt and you'll either get a poisonous gas, or
something that goes boom in contact with water.</annoyingly
pedantic>

Chemistry is really weird...