On 09/26/2016 02:42 AM, Jacob Carlborg wrote:
On 2016-09-25 20:16, Nick Sabalausky wrote:
I don't see why not, but there would be one notable drawback: You could
only have one instance existing at a time (per thread).
But how does it work in languages which don't pass in the state
explicitly, like with "yield" in C#?
Or async/await? I guess one doesn't call the function multiple times in
the same way instead it's done automatically under the hood, passing in
the state which might be stored in the "Task" that is returned?
I don't know about async/await, because all my C# work was with versions
of C# that predated those. But as for C#'s yield functions, yes, that's
my understanding: It's hidden magic automatically inserted by the compiler.
As a side note, that actually makes D's opApply a very interesting case,
really:
Instead of doing like the other implementations and "yielding" by
removing the top function from the callstack (ie "returning"), opApply
does the oppposite: It yields by pushing whatever function it's yielding
*to*, *onto* the callstack. So its state is stored on the stack, no need
for magic. The downside is, that's exactly what makes it impossible for
opApply to be used as a range (at least without introducing a true fiber
to save/restore the callstack): popFront *must* return in order for the
user's algorithm to call front and obtain the current element - because
that's how the range interface works.
The above code compiles, after removing the extra "return+case:".
Really? I may have to look into this more then.
Hmm, well for starters, according to
<http://dlang.org/spec/statement.html#GotoStatement>:
"It is illegal for a GotoStatement to be used to skip initializations."
Although if that's true, I don't know why that example compiled. Maybe
because "foo" wasn't used from "case 2:" onward? Maybe it failed to
notice the initialization since it was in an if condition? Or maybe the
compiler forgot to implement the same "can't skip initialization" check
for switch/case?