opApply/opApplyReverse return value types

Bill Baxter dnewsgroup at billbaxter.com
Wed Oct 18 18:56:52 PDT 2006

BCS wrote:
> Jarrett Billingsley wrote:
>> This works fine.  I am returning -49 from opApply and it works fine.  
>> I can return 0 from opApply and it works fine.  I honestly have no 
>> idea what the return from opApply is for.
> I would assume that the generated delegate different return value for 
> each goto and the return;
> void main(char argv[][])
> {
>     int i = argv.length;
>     foreach(a; new ForeachClass)
>     {
>         switch(i)
>         {
>             case 0: goto a;
>             case 1: goto b;
>             case 2: goto c;
>             case 3: goto d;
>             default: i/=4;
>             case 76: return;
>         }
>     }
>     a:    writef("hi\n"); return;
>     b:    writef("Wee\n"); return;
>     c:    writef("Zzzz\n"); return;
>     d:    writef("Hrumph\n"); return;
> }

Damn, is that the only reason?  Goto from inside a foreach must 
constitute less than 1% of all use cases.  It just doesn't seem right to 
expose the user to that kind of implementation detail in a core language 
construct.  And probably 99% of those goto usages have a simple 
workaround in the form of
     bool done = false;
     foreach(a; new ForeachClass)
                done = true;
                //goto FINISH; not from a block!

             case 76: return;
     if (done) goto FINISH;

And there's probably even something cleaner using exceptions or scope 

I wonder, can you goto out of an inner function?  If not, why should you 
be able to goto out of a foreach block?

Everyone raves about ruby blocks.  Do they have gotos?
I'm guessing no.  It seems D is /this/ close to being able to do 
everything that Ruby blocks can do.

The main difference between ruby blocks and D's foreach seems to be that 
in ruby, opApply effectively IS the foreach.  So in pseudo ruby:

     foreach(int i, &list.opApply)

Is something like
     list.opApply()(int i)

That makes a lot of sense.  Get rid of the foreach keyword.  In truth 
'foreach' knows nothing about 'foreach-ing'.  All it knows is how to 
call a delegate that knows how to foreach something.  But that delegate 
has no obligation to 'foreach'.  It can just as easily return one random 
item and stop.  So the terminology in D is *backwards*.  'foreach' is 
really something that knows how to apply a block-enclosing loop 
construct to a block.  'opApply' is really a method that knows how to go 
through the elements one-by-one.  'apply' should really be the D 
keyword.  'foreach' should be the method name:

     apply(int i, &list.foreach)

Wow.  This makes so much sense to me now.  That's why it seems so odd to 
have both foreach and foreach_reverse to me.  Because neither one really 
knows anything about iterating in the first place(*).  It's the methods 
that have that knowledge.  Everyone who doesn't know how ruby blocks 
work should really go take 30 minutes and read up on it and compare with 
how D does it. I found this link useful:

(*) Except for this pesky business about the special cases for arrays. 
And honestly, to me, I don't think the overhead is that serious an 
issue.  It's ok to say you pay a little penalty for using foreach on an 
array.  If you want the fastest speed, use the for loop.  But even with 
foreach, you're still going to have performance 10x better than the best 
foreach ruby or python can come up with.


More information about the Digitalmars-d-learn mailing list