On Sun, Sep 04, 2005 at 07:55:21 +0000, Luke Palmer wrote:
> Here's a good Perl 6 final exam question:
> 
> Spot the mistake (hint: it's not in the math):
> 
>     module Complex;
> 
>     sub i() is export { 
>         Complex.new(0,1)
>     }
>     multi sub infix:<+> (Complex $left, Complex $right) is export {
>         Complex.new($left.real + $right.real, $left.imag + $right.imag);
>     }
>     multi sub infix:<*> (Complex $left, Complex $right) is export {
>         Complex.new(
>             $left.real * $right.real - $left.imag * $right.imag,
>             $left.real * $right.imag + $right.real * $left.imag)
>     }
>     # ...
> 
> Give up?
> 
> When you add two complex numbers, you get into an infinite loop. 
> That's because infix:<+> adds things using the plus operator, which
> is, you guessed it, infix:<+>.  Now you'd think that multimethods
> would handle that, but they don't because by defining "multi sub
> infix:<+>" you are defining a *package* operator which *masks* the
> global operator!  So this turns into infinite recursion.

I always saw scoping of multis as something that applies to the
variants...

                multi sub foo {

                }

                {
                        my multi sub foo {

                        }

                        # the second variant is just for this scope, but 
neither masks
                        # the other
                }

> You must explicitly ask for masking

I think this should be an option... You can either mask off a single
variant by declaring one that overrides it in a tighter scope, with
yadda yadda as the body, or you could ask a whole scope to be
omitted from the possible variants.

>     2) Make multi automatically find the symbol that you would have
> referred to if the definition had not been there, and add a multi case
> to that symbol.  So in the example above, the innermost infix:<+> that
> existed before you said "multi" was *infix:<+>, so the multi
> definition would basically infer that you meant to say multi
> *infix:<+> and do the right thing.

I don't agree with this... It takes the lexical scoping semantics
out of things.

If multi's would cascade WRT to the scope of their definition, but
not mask, things should DWIM most of the time.

Please remember that when you declare a new multi you are usually
ammending to a commonly used operator, in order to extend it's
behavior in the scope that there is new data which much behave
accordingly.

There is one more problem though:

        class Complex {
                multi sub &infix:<*> { ... }
        }

        package Moose;
        use Complex;
        use SomeMathLib <function>;
        
        ...

        function($some_complex_number); # if function calls infix:<*> on
        # it's operand, somehow... What happens?

-- 
 ()  Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418  perl hacker &
 /\  kung foo master: /me spreads pj3Ar using 0wnage: neeyah!!!!!!!!!!!

Attachment: pgpuyVX8KG0i3.pgp
Description: PGP signature

Reply via email to