"Jacob Carlborg" <d...@me.com> wrote in message news:ie5n2o$2v7...@digitalmars.com... > On 2010-12-12 19:27, Nick Sabalausky wrote: >> >> There's one important difference you missed. Granted, it's not applicable >> in >> that particular example, but more generally, it's important: >> >> int foo() >> { >> foreach (person ; account.people) >> { >> writeln(person.name); >> if(blah) >> return 7; // Returns from foo >> } >> } >> >> >> int bar() >> { >> account.people.each((Person person) { >> writeln(person.name); >> if(blah) >> return 7; // Only tries to return from the delegate >> }); >> } >> >> In D, there is currently no way to convert "foo()" above to use a delgate >> (at least not without odd contorsions). So if we were to make syntax >> sugar >> for "bar()", it would get really confusing: >> >> int bar2() >> { >> account.people.each(Person person) >> { >> writeln(person.name); >> if(blah) >> return 7; // Only returns from the delegate, not bar2!! >> WTF?! >> } >> } >> >> There are similar issues with break, continue, and probably goto. >> >> In Ruby, the syntax sugar works out fine because you can make it work it >> either way. You can create something that behaves like a delegate >> ("return" >> only returns from the delegate), or you can create something that is >> treated >> as part of the function it's declared within ("return" unwinds the stack >> and >> returns from the function that created it). (Although Ruby leaves the >> choice >> up the the caller. I'm not entirely convinced that's the right way to do >> it.) >> >> D would need something similar for "passing a delegate" sugar to work out >> sensibly. One idea is to say that if-and-only-if the "sugar" is used, >> it's >> considered part of the original function that declared it rather than >> being >> a true degelate. The function that takes the "sugared delegate" must >> declare >> that it takes a "sugared delegate" instead of a normal one so that it can >> make sure not to do this: >> >> doSomething(); >> callSugaredDelegateThatMightUnwindTheStackEvenWithoutThrowing(); >> doCleanup(); > > Yes, absolutely correct, I totally forgot about this. D would need a way > to return from the delegate and a way to return from the context where the > delegate is called. Perhaps introduce a new keyword "yield"? >
I've been reminded in another branch of this thread that foreach/opApply already handles this issue, so that approach could probably just be copied. Ie with: foreach(item; somethingWithOpApply) { if(item.isItBoyant()) return item; } The body gets converted to a delegate which gets passed to opApply, but the "return" still works as expected. I would be interested to hear how exactly that works though, particularly when returning something other than void.