MiniD 2 - Tentative Release Candidate 1

davidl davidl at 126.com
Wed Dec 10 00:15:45 PST 2008


在 Wed, 10 Dec 2008 13:52:18 +0800,Jarrett Billingsley <jarrett.billingsley at gmail.com> 写道:

> On Wed, Dec 10, 2008 at 12:12 AM, davidl <davidl at 126.com> wrote:
>>
>> I got an impression that a scripting lang coroutine is less expensive than a function call? I guess coroutine in a scripting interpreted lang won't require any thread involved, and the suspension of the execution maybe even more costless compared to a return statement and reexecution of that function in the case of opApply.
>
> The cost of a coroutine object in MiniD, as well as the cost of
> calling it, depends on the compilation options
> (http://www.dsource.org/projects/minid/wiki/API2/CompilationOptions).
> If you don't specify any version flags when compiling MiniD, it will
> use tango Fibers for coroutines created from native functions, and
> will use its own system of pausing and resuming for coroutines created
> from MiniD functions.
>
> The cost of a coroutine resume/yield is more than a normal function
> call, but it's still not a lot.  For example, using MiniD coroutines,
> I can perform around 1.6 million resume/yield pairs per second on my
> Pentium M.  Fibers aren't much slower; I still get about 1.25 million.
>  That's not going to be a bottleneck considering the speed of most
> other operations.
>
> Rather, the biggest cost with a coroutine is memory.  A coroutine
> object is relatively large compared to a function closure, and
> depending on the compilation options, can also allocate D heap memory.
>  So for simple iteration tasks, it might be in the interest of
> performance to try to write it in the form of a function iterator, and
> if it gets to be too complex to be worth it, you can write it as a
> coroutine.
>
>> And I'm still not able to get opApply to work with coroutines, any example available?
>> I always get the error message of "Iterated coroutine must be in the initial state", I've no clue about what it's going on.
>
> When you use foreach on a coroutine, it has to be in the "initial"
> state.  The only times a coroutine can be in an initial state is (1)
> immediately after they are created, before they are called even once,
> and (2) after they have died and then had their .reset() method
> called.  A simple example:
>
> function count(x) =
>     coroutine function()
>     {
>         yield() // first "empty" yield is important for foreach-able coroutines
>         for(i: 1 .. x + 1)
>             yield(i) // yield values after that
>         // when this coroutine returns here, iteration stops
>     }
>
> foreach(v; count(4))
>     writeln(v) // prints 1 through 4
>

It's cool it could be used in that syntax. But I find nowhere of docs describing this feature?
Do I miss something?

Actually I tried something like:
module test
global v=coroutine function()
{
local opApply=coroutine function opApply(m)
{
local i=0
 if (i<3) {
 i++
 yield(i)
}
return null
}
yield()
}
v()
foreach(m;v)writefln(m)

In the case I wrote, the coroutine foreach just conflicts with the coroutine foreach way you illustrate
in your example. As I didn't have that information, I tried to perform my coroutine foreach in a standardized 
opApply way. That's somewhat confusing for people not having the knowledge of coroutine foreach.
Intuitively, the foreach is presumably working in the way of calling instance's opApply func and passing the arg
of reverse or not to it. While the truth is I'm wrong. 
 
The inconsistency seems to be a tradeoff. Yes, without opApply it looks clean. While it's inconsistent. That means
developers who use minid need to learn more. 

The following case illustrates a easily misread code for me at least. In minid, I thought the parentheses
were compulsive, cause the coroutinefunc.state won't work, but coroutinefunc.state(). So in such case, I guess the
"count" refers to the function object, while the result shows it just endless loop and results stack overflow. 
Even that "count" actually a function call without the arg, the calling is performed. that's somehow misleading.

function count(x) 
{
    function opApply(m) = coroutine function opApply(m)
    {
        for(i: 1 .. x + 1)
            yield(i) // yield values after that
        return null
    }
    foreach(v;count)
        writeln(v) // prints 1 through 4
}
count(4)
object.Exception: Stack Overflow

MDCL stack overflowed out, maybe mdcl should do something to protect itself from stack overflowing.

I'm trying to use coroutine foreach in a class.

class count 
{
    x =3
    function opApply(m) = coroutine function opApply(m)
    {
        yield()
        for(i: 1 .. m.x + 1)
            yield(i) 
    }

}
global c= count()
    foreach(v;c.opApply(c))
        writeln(v) // prints 1 through 4

it causes of runtime error: Error: opApply(7): Attempting to access field 'x' from a value of type 'null'

The problem here is I misuseing the function definition. 
function opApply(m) = coroutine function opApply() works OK.

But that's inconsistent from a strong type user's view. Because the left part is function with 1 arg, right part
is a coroutine function without any arg. That's pretty error-prone for newbies. 

Also the class coroutine foreach tries as follows failed:

class count 
{
    x =3
    function opApply(m) = coroutine function opApply()
    {
        writefln(m) // prints null, that's pretty astonishing for me.
        for(i: 1 .. x + 1)
            yield(i) 
    }

}
global c= count()
    foreach(v;c)
        writeln(v) // prints 1 through 4
the result is printing nothing, and no runtime error.


If I modify the loop to 
    for(i: 1 .. :x + 1)
            yield(i) 
runtime error shows up:
Error: opApply(7): Attempting to access field 'x' from a value of type 'null'

Seems there's no easy way of using coroutine foreach with class instance?

> Notice that count is returning a new coroutine object each time you
> call it, so the coroutine is always in the "initial" state.
>
> There's more info on coroutines, including showing some iterators and
> explaining their various states, at the following link:
>
> http://www.dsource.org/projects/minid/wiki/LanguageSpec2/Functions#Coroutines
> 




More information about the Digitalmars-d-announce mailing list