Piers Cawley writes: > Simon Cozens <[EMAIL PROTECTED]> writes: > > But it isn't, and I don't know why it isn't, and so we end up > > spending loads of time discussing things that can be punted out to > > modules. Designing Perl 6 is hard enough; let's not try to fill > > CP6AN at the same time. > > But the vast majority of us *aren't* designing Perl 6, that's Larry > and his team's job. We're in the position of taking the work that's > been done on the language so far and working out how we'd use it (and > yes, we're in the business of thinking about the sort of thing > that will go in CP6AN). Considered in that light, Luke's question is a > really good one, it points up an ugly idiom and considers how one > would generate a better idiom in Perl 6. Where he falls down is in > proposing new syntax to solve the problem rather than in proposing the > new syntax and then offering a sketch of its implementation as a macro > in Perl 6. After all, problems with 'implemented' solutions are simply > demonstrations that the design is sound, and that's good feedback to > Larry and his team. These things only become real design issues if > there appears to be no good way to solve such problems.
Ok, back to the concrete side of things then. How *would* one implement a new loop hook? Let's look at C<while>. It might be implemented as such: my sub while_impl(&cond, &block) { my &cc := Continuation.new; try { &block.PRE.() if &block.PRE; if cond() { block(); throw X::Next; } else { throw X::Last; } CATCH { when X::Next { &block.NEXT.() if &block.NEXT; cc() } when X::Last { &block.POST.() if &block.POST; } } } } macro while($cond, $block) { my (&cond, &block) := ($cond, $block)Â.Âparse; return -> { while_impl(&cond, &block) } } Neglecting things like C<redo>. And so to implement FINISH, you'd need to stick a C<&block.FINISH.() if &block.FINISH> right before C<throw X::Last>. But it would be really nice if you could do this without rewriting C<while>. One way is to wrap &cond: wrap &cond: { call or &_.FINISH.() }; But then you need to associate FINISH with the condition instead of the execution block. Or just wrap it when you can see the FINISH block. Like: macro FINISH($code) { # When it's a macro/rule, caller naturally returns the parse stack CallerContext $c = caller &Perl6::Grammar::while; my &code := $code.parse; $c[-1].MY.{'&cond'}.wrap({ call or code() }); return -> {}; } Okay, that's pretty evil. Pretty really evil. I took a currently executing sub, extracted, and I<changed> one of its lexicals. Evil enough to make the optimizer very unhappy, in any case. But such is the life of the Aspect-Oriented programmer. Can anyone think of a cleaner way? Luke Ã