Re: Musings on operator overloading

2008-03-27 Thread Larry Wall
On Thu, Mar 27, 2008 at 09:02:37AM -0600, Thom Boyer wrote:
> Larry Wall wrote:
>> The .++ form is still not a method (single) dispatch, just an alternate
>> form of the postfix, which is a multi dispatch.  
>
> But the postfix is a unary operator, right? So that'd be multi dispatch on 
> one argument.

Correct.

> How does single dispatch differ from multi dispatch on a single argument?

The question is, who's to be master, that's all.  :)

Single dispatch asks the object's MOP (meta-object protocol) to
dispatch through its .HOW interface, so it depends on which metaobject
system the object was born under.

Multiple dispatch, in contrast, pays attention only to the type
information that comes from the .WHAT interface, and doesn't ask
the MOP to do the dispatch.  It is external to any MOP, except
insofar as the MOP gets involved to help define how .WHAT returns
type information.  But types are considered largely declarative,
not procedural.

(This view of single dispatch is slightly oversimplified, insofar
as the MOP typically sets up an efficient responder interface that
handles the actual dispatch without having to redecide every time.)

Practically speaking, the main difference is "foo $x" looks for
a function with one argument, while $x.foo looks for a method
with no arguments.

multi sub foo ($x) { say "I am a function" }
vs.
method foo () { say "I am a method" }

The candidate list for multis is constructed from all longnames visible
in the current lexical scope, and there is no inheritance involved,
only importation of function names (which, for so-called built-in
functions, is done by the Prelude from the various modules those
functions are defined in).

The candidate list for methods is determined by the MOP, but generally
follows class hierarchy for class-based OO.

A routine can be visible via both routes, but only by some form of
aliasing.  The "close" method/function is defined something like:

class IO;
...
method close () is export {...}

and when the Prelude does "use IO" it imports the close method not
as method, but as a function, as if you'd said:

multi close (IO $self) {...}

or some such.

And since mutlis are lexically scoped, and operators are just macros
that translate to function calls, and longnames from different scopes
are interleaved, it means we have lexically-scoped overloading if
you want it.

The other ramification is that we get to define our operators
independently of what the object might think the operator means,
even if it comes from another language.  These may mean two entirely
different things if $a comes from, say, Python or Java or Perl 5:

$a + $b # always addition in Perl 6
$a.'+'($b)  # depends on language of $a

More subtly, the same distinction happens with unaries:

+$a # always numification in Perl 6
$a.prefix<+># depends on language of $a

Larry


Re: Musings on operator overloading

2008-03-27 Thread Thom Boyer

Larry Wall wrote:

The .++ form is still not a method (single) dispatch, just an alternate
form of the postfix, which is a multi dispatch.  


But the postfix is a unary operator, right? So that'd be multi dispatch 
on one argument.


How does single dispatch differ from multi dispatch on a single argument?
=thom


Re: Musings on operator overloading

2008-03-27 Thread Larry Wall
On Thu, Mar 27, 2008 at 09:46:29AM -0400, Mark J. Reed wrote:
: Is it just me, or is all this talk about precedence and functions vs
: operators vs methods creating a niggling sensation in anyone else's
: head?  It feels like we're in the vicinity of another one of them Big
: Simplifying Idea things.  Unfortunately, I don't have the actual Big
: Idea, so it could just be a false alarm.

We're in the vicinity of a lot of big ideas here, but most of them are
already thunk of and documented in one of the synopses.  I think any
additional Big Simplifying Ideas at this point would only simplify
things for us, not for the user (which is the usual failure mode of
Big Simplifying Ideas).

: On the one hand, I'm worried that Perl6 is going to turn into the
: computer equivalent of Quenya, which was never completed because its
: creator couldn't stop tinkering.  (No offense to Larry intended..)  On
: the other, given how much design thought has gone into it thus far,
: much of it radical, it would be terrible to miss an opportunity to do
: something great in the rush to git 'er done.

Um, you're missing something basic here; most of the radical design we
have so far is there *precisely* because it will allow us to publish
snapshots of the language without ever finishing the language.  :)

If you can't fix it, feature it...

Larry


Re: Musings on operator overloading

2008-03-27 Thread Larry Wall
On Thu, Mar 27, 2008 at 01:08:43PM +0100, TSa wrote:
> HaloO,
>
> TSa wrote:
>> Another good use of the dot forms is to get a single character
>> form to tighten precedence: $x**3! != $x**3.! == $x**(3!).
>
> BTW, is the dot form only available for postfix or for infix
> as well? I.e. 3 * 2 == 3.*(2)?

Only postfix.  (And we already use .* for something else.)  You can
probably get away with 3.infix:<*>(2) though.

However, note also that operators are intended to be dispatch
using multiple dispatch, not single.  Multiple dispatch allows the
language to defined the operator without getting the object involved.
Single dispatch has to rely on the semantics of the object itself to
determine the meaning of a method.  This becomes important when we
have objects from outside of Perl.  $a + $b is always addition under
multiple dispatch, but $a.infix:<+>($b) might do concatenation if $a
is a foreign object from a language that (mis)treats + that way.

Larry


Re: Musings on operator overloading

2008-03-27 Thread Larry Wall
On Thu, Mar 27, 2008 at 01:01:27PM +0100, TSa wrote:
> HaloO,
>
> Larry Wall wrote:
>> I deem that to be an unlikely failure mode, however.  So maybe .++
>> is just gone now, and you have to write \++ instead.  Any objections?
>
> Please keep .++ as outlined below. Does the degenerate unspace not
> collide with &prefix:<\>? That is does foo\bar() not mean to capture
> the result from bar() and call foo with it unflattened?

No, listops require a space after if there are any arguments.

>> I'm not sure that's a great loss.  It does suggest an alternate
>> approach, though, which is to keep the .() forms with forced method
>> precedence, and only require \x form for alpha postfixes that want
>> to keep their own precedence.  Not sure if I like that entirely,
>> but it could fall out naturally from the definition of unspace in
>> the current scheme of things, so maybe it's a non-issue.
>
> As it stands the .() forms are a great way to stack ops after
> a term. Together with knowing about the ops on the symbolic unary
> level you can easily read expressions from the terms outwards.
> Good practice would then be to join these extended terms by an
> obvious set of infix ops---usually one. The only twists to learn in
> this scheme would be ++, -- and **.

I don't follow that.  Example?

> Another good use of the dot forms is to get a single character
> form to tighten precedence: $x**3! != $x**3.! == $x**(3!). This
> is kind of reverse visually, though.

Unless you count precedence forcing as "more work" in some sense.  :)

> So one might be tempted to
> make ! tighter than ** and get the looser meaning with $x**2\!
> which wouldn't be a degenerate unspace but a special form to
> unbind a tight op as in $x**$y\++ == ($x**$y)++ disregarding the
> fact that $x**$y is no lvalue.

That seems unnecessarily convoluted for a rarely used item.

> BTW, are there still the * and ** prefix ops for list flattening?
> Or are these superseded by prefix |?

The * and ** prefixes are gone.  We have * and ** as bare terms
now, which precludes their being used as a prefix.  Lists may be
dereferenced into capture context with |, or into list context with
@ or @@.

>> and maybe even
>>
>> &circumfix:<| |> ::= &prefix:;
>> |$x|
>>
>> except for the fact that that would collide with prefix:<|>...
>
> So no whitespace dwimmery here? I.e. one would need |$x | to
> force the second | into infix? But eventually the parser has
> to give up when the same symbol is overloaded as prefix, postfix,
> infix and symmetric circumfix anyway.

We don't do that kind of lookahead, nor should we force the reader to
do it.  Circumfixes are recognized only by their initial token, and
therefore live in the same slot as prefixes.  The final token is used
only to validate the termination of the inner expression.  Any other
approach is likely to confuse both the compiler and the user.

Note that the human brain is not well wired to do lookahead in
linguistic processing, since you'd have to know what was not yet
uttered by the speaker.  N-token lookahead schemes are good for
academic papers but not so good for users.  You can cheat a bit
visually, but it's not terribly efficient to have to glance ahead in
any case.

Larry


Re: Musings on operator overloading

2008-03-27 Thread Larry Wall
On Wed, Mar 26, 2008 at 07:32:23PM -0600, Thom Boyer wrote:
> Question: given
>
> ($x)++   # no whitespace, so postfix?
>
> is ++ postfix, or infix?

That is postfix.  Any infix that could be confused with a postfix
requires intervening whitespace.

> Now, I think that
>
> $x.foo
>
> is a method call, even if there's a postfix: declaration in scope. And 
> that's a problem, because, no matter what precedence postfix: was 
> given,
>
> 1,2,3.foo
>
> is still going to mean
>
> 1, 2, (3.foo)
>
> instead of the desired
>
> postfix:(1,2,3)
>
> so Larry has proposed
>
> 1,2,3\foo   # means: postfix:(1, 2, 3)
>
> as a way to get the desired meaning without having to resort to parentheses.
>
> So the point is that a nospace unspace acts like dot, in that it turns the 
> following operator into a postfix operator. But it doesn't have the 
> undesired characteristic that it turns an intended postfix operator into a 
> method dispatch. Have I got that right, or am I still wandering in a 
> wilderness that is completely disconnected from Larry's proposal?

The .++ form is still not a method (single) dispatch, just an alternate
form of the postfix, which is a multi dispatch.  The basic problem
is that .i is ambiguous, and by the current standard grammar is
not resolved by LTM because it's a tie.  We could maybe fix that by
changing it so the "meth" part of .meth isn't counted as part of the
same token, but right now it is.  Or we could bias .meth forms toward
single dispatch (which might work the same, depending on whether there's
an equivalent method definition, which often there is, especially if
the multi is defined as just an exported method).

> Final question: I think these are all equivalent. Are they?
>
> 1,2,3\foo
> (1,2,3)foo
> (1,2,3).foo
> postfix:(1,2,3)

At the moment, the .foo form is officially ambiguous, so might end up
going through single dispatch instead of multi dispatch.  To the casual
reader it looks like it should be single dispatch.  That's what
is bugging me.  Well, one of the things...

The current tie-breaker on longest token matching is to use rule
ordering, but that's not terribly robust.

Larry


Re: Musings on operator overloading

2008-03-27 Thread Mark J. Reed
Is it just me, or is all this talk about precedence and functions vs
operators vs methods creating a niggling sensation in anyone else's
head?  It feels like we're in the vicinity of another one of them Big
Simplifying Idea things.  Unfortunately, I don't have the actual Big
Idea, so it could just be a false alarm.

On the one hand, I'm worried that Perl6 is going to turn into the
computer equivalent of Quenya, which was never completed because its
creator couldn't stop tinkering.  (No offense to Larry intended..)  On
the other, given how much design thought has gone into it thus far,
much of it radical, it would be terrible to miss an opportunity to do
something great in the rush to git 'er done.


Re: Musings on operator overloading

2008-03-27 Thread Thom Boyer

Jon Lang wrote:

Thom Boyer wrote:

 That seems better to me than saying that there's no tab character in

 say "blah $x\t blah"


Whoever said that?


Oops. I thought Larry did. But he didn't; I misread it. Whew.

Somehow I managed to read Larry's words and get exactly the *opposite* 
meaning from what he actually wrote:


Larry Wall wrote:
> This may also simplify the parsing rules inside double quoted
> strings if we don't have to figure out whether to include postfix
> operators like .++ in the interpolation.  It does risk a visual
> clash if someone defines postfix::
>
> $x\t   # means ($x)t
> "$x\t"   # means $x ~ "\t"

How embarrassing. Thanks for asking "Whoever said that?", because it 
forced me to go reread it.


I think I'd better go reread the whole thing. More carefully this time.


> Thom Boyer wrote:
>>  when (if I understand correctly) you could write that as simply as
>>
>>  1,2,3 say
>
> Nope.  This is the same situation as the aforementioned '++' example,
> in that you'd get into trouble if anyone were to define an infix:
> operator.

OK. Let me see if I get this. First, let me state my understanding of 
the issue with ++ (where ++ is actually a stand-in for *any* operator 
that is both postfix and infix):


$x++ # postfix operator, because there's no whitespace
$x.++# postfix (the dot is optional)

$x ++# infix operator, because there's whitespace

$x\   ++ # postfix: space isn't allowed, but unspace is
$x\  .++ # postfix (the dot is still optional)


Question: given

($x)++   # no whitespace, so postfix?

is ++ postfix, or infix?


Now, I think that

$x.foo

is a method call, even if there's a postfix: declaration in scope. 
And that's a problem, because, no matter what precedence postfix: 
was given,


1,2,3.foo

is still going to mean

1, 2, (3.foo)

instead of the desired

postfix:(1,2,3)

so Larry has proposed

1,2,3\foo   # means: postfix:(1, 2, 3)

as a way to get the desired meaning without having to resort to parentheses.

So the point is that a nospace unspace acts like dot, in that it turns 
the following operator into a postfix operator. But it doesn't have the 
undesired characteristic that it turns an intended postfix operator into 
a method dispatch. Have I got that right, or am I still wandering in a 
wilderness that is completely disconnected from Larry's proposal?


Final question: I think these are all equivalent. Are they?

1,2,3\foo
(1,2,3)foo
(1,2,3).foo
postfix:(1,2,3)

=thom


Re: Musings on operator overloading

2008-03-27 Thread TSa

HaloO,

Jon Lang wrote:

TSa wrote:

 Note that I see ** more as a parametric postscript then a real binary.
 That is $x**$y sort of means $x(**$y).


That's where we differ, then.  I'm having trouble seeing the benefit
of that perspective, and I can clearly see a drawback to it - namely,
you have to think of infix:<**> as being a different kind of thing
than infix:.«<+ - * />, despite having equivalent forms.


I see no drawback but a necessity because of the following asymmetry:

  3 * 2 == 3 + 3 == 2 + 2 + 2;
  3 **2 == 3 * 3 != 2 * 2 * 2;

So ** more behaves like 3.pow(2) and overloading ** with
non-numeric types on the right is questionable. Certain
overloads of the left side might even require the right
side to be (unsigned) integer. And of course

 $any ** $int === [*]($any xx $int)

should hold.


Regards, TSa.
--

The Angel of Geometry and the Devil of Algebra fight for the soul
of any mathematical being.   -- Attributed to Hermann Weyl


Re: Musings on operator overloading

2008-03-27 Thread TSa

HaloO,

TSa wrote:

Another good use of the dot forms is to get a single character
form to tighten precedence: $x**3! != $x**3.! == $x**(3!).


BTW, is the dot form only available for postfix or for infix
as well? I.e. 3 * 2 == 3.*(2)?


Regards, TSa.
--

The Angel of Geometry and the Devil of Algebra fight for the soul
of any mathematical being.   -- Attributed to Hermann Weyl


Re: Musings on operator overloading

2008-03-27 Thread TSa

HaloO,

Larry Wall wrote:

I deem that to be an unlikely failure mode, however.  So maybe .++
is just gone now, and you have to write \++ instead.  Any objections?


Please keep .++ as outlined below. Does the degenerate unspace not
collide with &prefix:<\>? That is does foo\bar() not mean to capture
the result from bar() and call foo with it unflattened?



I'm not sure that's a great loss.  It does suggest an alternate
approach, though, which is to keep the .() forms with forced method
precedence, and only require \x form for alpha postfixes that want
to keep their own precedence.  Not sure if I like that entirely,
but it could fall out naturally from the definition of unspace in
the current scheme of things, so maybe it's a non-issue.


As it stands the .() forms are a great way to stack ops after
a term. Together with knowing about the ops on the symbolic unary
level you can easily read expressions from the terms outwards.
Good practice would then be to join these extended terms by an
obvious set of infix ops---usually one. The only twists to learn in
this scheme would be ++, -- and **.

Another good use of the dot forms is to get a single character
form to tighten precedence: $x**3! != $x**3.! == $x**(3!). This
is kind of reverse visually, though. So one might be tempted to
make ! tighter than ** and get the looser meaning with $x**2\!
which wouldn't be a degenerate unspace but a special form to
unbind a tight op as in $x**$y\++ == ($x**$y)++ disregarding the
fact that $x**$y is no lvalue.

BTW, are there still the * and ** prefix ops for list flattening?
Or are these superseded by prefix |?



and maybe even

&circumfix:<| |> ::= &prefix:;
|$x|

except for the fact that that would collide with prefix:<|>...


So no whitespace dwimmery here? I.e. one would need |$x | to
force the second | into infix? But eventually the parser has
to give up when the same symbol is overloaded as prefix, postfix,
infix and symmetric circumfix anyway.


Regards, TSa.
--

The Angel of Geometry and the Devil of Algebra fight for the soul
of any mathematical being.   -- Attributed to Hermann Weyl


Re: Musings on operator overloading

2008-03-27 Thread Thom Boyer

Thom Boyer wrote:
And does dot always do that? If it does, then something odd happens. 
Consider infix:<*> and postfix:, where infix:<*> binds tighter than 
postfix:<+>, and both bind more loosely than dot. Then


I meant "... tighter than postfix:, ..."



1 * 2!  # means (1 * 2)!
1 * 2.! # means 1 * (2!)

Methinks one or more of my assumptions is erroneous, 'cuz that's just 
too ugly to live.

=thom




Re: Musings on operator overloading

2008-03-27 Thread Thom Boyer

Thom Boyer wrote:

Now, I think that

$x.foo

is a method call, even if there's a postfix: declaration in scope. 
And that's a problem, because, no matter what precedence postfix: 
was given,


1,2,3.foo

is still going to mean

1, 2, (3.foo)

instead of the desired

postfix:(1,2,3)



The way I wrote that, it sounds like I think postfix: isn't a 
method call, but of course it is.


What I really meant to say is that, in

1,2,3.foo

the precedence of foo gets changed to the precedence of dot. I don't 
actually know that that is true. Is it?


And does dot always do that? If it does, then something odd happens. 
Consider infix:<*> and postfix:, where infix:<*> binds tighter than 
postfix:<+>, and both bind more loosely than dot. Then


1 * 2!  # means (1 * 2)!
1 * 2.! # means 1 * (2!)

Methinks one or more of my assumptions is erroneous, 'cuz that's just 
too ugly to live.

=thom