Piers Cawley writes:
: Also known as constructs you wish you hadn't discovered.
: 
: So, I'm reading through Finkel and I came across the following, which
: computes the greatest common divisor of a and b (recast into perl6ish
: syntax)
: 
:   while {
:     when $a < $b { $b -= $a }
:     when $b < $a { $a -= $b }
:   }
: 
: The idea is that the loop keeps on looping until none of the guard
: conditions match. This can be redone in 'real' Perl 6 as
: 
:   while 1 {
:     given 1 {
:       when $a < $b { $b -= $a }
:       when $b < $a { $a -= $b }
:       else { last }
:     }
:   }

Well, it's "default", not "else", but it's redundant in any case, since
the C<when>s would fall through.

: I'm not sure about the 'break'ing behaviour of a C<when> that isn't in
: a C<given> block so I've introduced a 'dummy' one here. Maybe Larry
: can clarify.

Could be written:

    loop {
      when $a < $b { $b -= $a; next }
      when $b < $a { $a -= $b; next }
      last;
    }

A C<when> that is a boolean doesn't reference a given.  It'd be nice to
get rid of the C<next>, but C<loop> isn't naturally a topicalizer.
Could say:

    for 0..Inf {
      when $a < $b { $b -= $a }
      when $b < $a { $a -= $b }
      last;
    }

The optimizer might well pick up that $_ is unreferenced and optimize
the 0..Inf away.  Still, the first way looks cleaner to me.

: So, do we want this monstrosity? I confess that I did find myself
: using something like it occasionally when I was working on the scheme
: evaluator, but it looks very weird indeed.

Depending on whether we define -> as the "topicalizing arrow", we might
be able to go as far as

    loop -> {
      when $a < $b { $b -= $a }
      when $b < $a { $a -= $b }
      last;
    }

That makes C<given> and C<for> special cases, in that they default to
C<< -> $_ >> when you don't supply the topic arrow.  Defining ->
this way has the additional advantage of providing a clean way
to say "there is no topic for this closure".  I believe the apo had

    given () { ... }

but this way we could have

    given -> { ... }

and guarantee that all the tests are boolean.  Plus -> could be used
anywhere else that made sense to hang an argumentless block.

It could be argued that bare

    -> { ... }
    
should default to

    -> $_ { ... }

but I think the fact that C<for> and C<given> already default to $_
makes that not so important.  Plus we'd have to write something like

    -> () { ... }

to mean argumentless, and that's not so nice.  So I think a bare topic
arrow means topicless.  (Careful how you say that.)

Anyway, much of the time you want a topic, you'd want to write

    -> $_ is rw { ... }

In fact, that's what C<for> and C<given> actually default to, I think.

Larry

Reply via email to