>> Some related issues:
>> 
>>     1) Did Larry or did he not mention something about dealing with
>>        indirect object more cleanly?

>Maybe clarify this just a little. I don't think I was present for this
>discussion.

That's just the indirect object slot ambuiguity annoyance.  See the
OO chapter in Camel3 for a treatment:

    =head2 Syntactic Snafus with Indirect Objects

    One syntax will often be more readable than the other.  The
    indirect object syntax is less cluttered, but suffers several
    forms of syntactic ambiguity.  The first is that the R<LIST>
    part of an indirect object invocation is parsed the same as any
    other list operator.  Thus, the parentheses of:

        enchant $sword ($pips + 2) * $cost;

    are assumed to surround all the arguments, regardless of what comes
    afterward.  It would therefore be be equivalent to this:

        ($sword->enchant($pips + 2)) * $cost;

    That's unlikely to do what you want: C<enchant> is only being
    called with C<$pips+2>, and the method's return value is then
    multiplied by C<$cost>.  As with other list operators, you must
    also be careful of the precedence of C<&&> and C<||> versus
    C<and> and <or>.  For example, this:

        name $sword $oldname || "Glamdring";   # can't use "or" here!

    becomes the intended:

        $sword->name($oldname || "Glamdring");

    but this:

        speak $mage "friend" && enter();        # should've been "and" here!

    becomes the dubious:

        $mage->speak("friend" && enter());

    Which could be fixed by rewriting into one of these equivalent forms:

        enter() if $mage->speak("friend");
        $mage->speak("friend") && enter();
        speak $mage "friend" and enter();

    The second syntactic infelicity of the indirect object form is
    that its R<INVOCANT> is limited to a name, an unsubscripted
    scalar variable, or block.<footnote> Attentive readers will
    recall that this is precisely the same list of syntactic items
    that are allowed after a funny character to indicate a variable
    dereference--for example, C<@ary>, C<@$aryref>, or
    C<@{$aryref}>.</footnote> As soon as the parser sees one of
    these, it has its R<INVOCANT>, so it starts looking for its
    R<LIST>.  So these invocations:

        move $party->{LEADER};               # probably wrong!
        move $riders[$i];                    # probably wrong!

    actually parse as these:

        $party->move->{LEADER};
        $riders->move([$i]);

    rather than what you probably wanted:

        $party->{LEADER}->move;
        $riders[$i]->move;

    The parser only looks a little ways ahead to find the invocant
    for an indirect object, not even as far as it would look for a
    unary operator.  This oddity does not arise with the first
    notation, so you might wish to stick with the arrow as your
    weapon of choice.

    Even English has a similar issue here.  Think about the command,
    "Throw your cat out the window a toy mouse to play with."  If
    you parse that sentence too quickly, you'll end up throwing the
    cat, not the mouse (unless you notice that the cat is already
    out the window).  Like Perl, English has two different syntaxes
    for expressing the agent: "Throw your cat the mouse" and "Throw
    the mouse to your cat."  Sometimes the longer form is clearer
    and more natural, and sometimes the shorter one is.  At least
    in Perl, you're required to use braces around any complicated
    indirect object.


--tom

Reply via email to