Trey Harris wrote:

>>      sub repeat is multi ($desc is valued(1),  &body) {
>>          body(1);
>>      }
>>
>>      sub repeat is multi ($desc is valued(0),  &body) {
>>      }
>>
>>      sub repeat is multi ($desc is valued(['A'..'F']),  &body) {
>>          die "Can't repeat hexadecimally";
>
> This is very nice.  But ordering of multimethod declarations suddenly
> matters, doesn't it?  With simple multimethods based on class structures,
> you use the best match (if the actual argument is Integer, I'll prefer the
> method where the corresponding signature is Integer, then Rational, then
> Real, then Complex), right?  But with this mechanism, you just have
> boolean acceptance of the argument, so I assume that ordering will be how
> you decide which multimethod to call--the first to accept its argument
> wins.

I would much prefer to see it still checking all variants (i.e. use exactly
the same multiple dispatch mechanism. By default, a value match would cost
zero, but you could specify the actual cost, just as you can with class-based
multiple dispatch in Perl).

In the case of multiple variants matching, the normal exception would be
thrown (unless there was a default variant).


> Yes.  I think it works great as a C<map> replacement.  For a C<grep>
> replacement, it's a little unwieldy:
> 
> P5:
>    @odds = grep { $_ % 2 } @nums;
> 
> P6:
>    @odds = for @nums { next unless $_ % 2; $_};

Sure. But simple cases like that are what C<grep> is for.

As with C<map>, the C<for>-ish version of C<grep> is better applied when the
block gets nasty:

P5:
        @special = grep { is_prime($_) &&
                          $_**2 % 3 &&
                          do { @fp1 = factors($_+1);
                                @fm1 = factors($_-1);
                                my $intersects;
                               check: foreach my $fp1 (@fp1) {
                                   foreach my $fm1 (@fm1) {
                                       $intersects =1 and last check
                                            if $fp1 == $fm1;
                                   }
                               }
                               $intersects && @fp1>2 && @fm1>2;
                             }
                          } @nums;

P6:
        @special = for @nums {
                          next unless is_prime($_) && $_**2 % 3;
                          @fp1 = factors($_+1);
                           @fm1 = factors($_-1);
                           next unless @fp1=~@fm1 && @fp1>2 && @fm1>2;
                          $_;
                    }

Damian


Reply via email to