>> 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