Re: Musings on operator overloading

2008-03-20 Thread David Green

On 2008-Mar-19, at 1:40 pm, Mark J. Reed wrote:

On Wed, Mar 19, 2008 at 1:01 PM, Larry Wall [EMAIL PROTECTED] wrote:

The use of + in Python or  in C++ is, I think, primarily the
violation of a *linguistic* principle, not a mathematical principle.


Maybe it's just 'cause I cut my teeth on BASIC, but + for string  
concatenation has always felt pretty natural.


That's because it is natural.  Kids don't have to be very old to get  
the joke in 1+1=11.  People just naturally think of plus or a plus- 
sign as a synonym for and.  In a non-technical context, I bet we all  
scribble down '+'s on notes and grocery lists, etc. to stand for any  
of Perl's: + ~ , ;  .  It's not that there isn't ambiguity, but  
it's an ambiguity that we're used to dealing with in everyday life, so  
it maps easily onto a programming language.


Not that I'm saying separate operators are a bad thing.  When  
programming, we do often have to mix numbers and strings in all sorts  
of ways, so Perl's + and ~ are often a better match for the problem- 
space.  It may require marginally more effort to get used to than  
BASIC's dual-purpose +, but I'm not sure even that's true, since we  
really are used to distinguishing addition from concatenation, even in  
grocery lists -- it's just that we humans are a lot better about  
understanding context than machines are, so we implicitly translate  
plus signs into one or the other on the fly.


(Actually, Perl6 allows for context in a way that earlier Perls  
didn't: you can declare something to be a Num or a Str, and then a  
single overloaded + would work; in the old days when scalars had  
split personalities, you needed to specify the type some other way --  
in the operator.  Interestingly, BASIC has gone the other direction --  
at least, Visual BASIC uses + for addition and  for concatenation;  
I'm guessing this happened when VB got variant types that could hold  
either numbers or strings.)



While I agree with the sentiment of not arbitrarily restricting
people from doing ugly things unless they ask for such restrictions,
Agreed... though I disagree that the sort of overloading under  
discussion (/ for separating paths) falls into the ugly things  
category.


It's not ideal, but it's a fact of life.  Slashes for path separators  
are such a widespread custom that it would make as much sense to give  
up slashes for division.  (Actually, it would make more sense to keep  
slashes for paths and switch to ÷ (U+00F7) because the real division  
sign is at least as widespread for division, and isn't ambiguous in  
all the other ways slashes are, such as random separators on grocery  
lists.)


Whereas it is common to find addition and concatenation in the same  
expression, it's very uncommon to find division and path-building  
going on at the same time.  Path-building plus string-concat'ing *is*  
a likely and reasonable combination, though, so I would be against  
using ~ for joining paths.


(It is tempting to want a leading / to start an absolute path, and  
./ to introduce a relative path, but those are ambiguous with regex  
delimiters and a $_ method.  (Although ./ could probably work by the  
longest-token rule?)  However, it's not a hardship to do something  
like: io $foo/$bar, or io /$foo/$bar, where io() is an IO-object  
constructor -- those example thus being: io($foo) / $bar, or io() /  
$foo / $bar.)


The typical user already has a good notion of what the common  
operators

are, and what they mean.  So while drastically changing the meaning
of one of those operators may not be a disservice to the writer of
the code, it may well be a disservice to the reader.


Which is why I hope P6 defines standard symbols in the standard  
way.  (Where by standard I mean symbols that have a well-defined  
popular meaning, e.g. ÷, ≤, ∈, ±, ¬.  Well, and a meaning that's  
useful to Perl... ♂ and ♀ are well-defined, but I don't know how  
you'd use them in P6.  (I guess they could be enums!))


I agree *changing* the meaning is bad.  But the Good Kind of  
operator overloading doesn't do that; it just adds a new meaning.   
It really is overloading.


Yup, again because overloading is natural to human communication.   
And of course being so flexible about how to balance mapping onto the  
way humans think vs. mapping onto the problem space is what makes P6  
so delightful.


Which is why I like it so much more than certain of its brethren  
with their Orthogonality Ueber Alles attitude.  I just don't want to  
see that sort of prescriptivity creep in to Perl.



(Unless it's predeclared, of course!!)


-David



Re: Musings on operator overloading

2008-03-20 Thread Mark J. Reed
On Thu, Mar 20, 2008 at 2:24 AM, David Green [EMAIL PROTECTED] wrote:
  Interestingly, BASIC has gone the other direction --
  at least, Visual BASIC uses + for addition and  for concatenation;
  I'm guessing this happened when VB got variant types that could hold
  either numbers or strings.

Actually, VisualBASIC (at least as of VB.NET/2008) still has + for
concatenation, too.   is preferred because of the complex set of
rules that determine when + does conversions and when it doesn't (for
instance, adding a stringish Object to a numeric Object wll in some
cases convert the string to a number and add instead of
concatenating!), but + still works.


-- 
Mark J. Reed [EMAIL PROTECTED]


Re: Musings on operator overloading

2008-03-20 Thread TSa

HaloO,

Mark J. Reed wrote:

For the record, I am opposed to any restriction on operator
overloading that requires mathematical properties to hold.  ANYTHING
is fair if you predeclare.


Hmm, my idea is more about defining interfaces that allow to detach
implementation of (numerical) algorithms from datatypes. E.g. the
Euclidean algorithm to find the gcd requires division and a remainder
that decreases in absolute value. This is like sorting objects that
do the Ordered role.



Besides, there is nothing that inherently
associates the / symbol with division - it's only an ASCII
approximation of fraction notation.


We all know that ASCII is a rather limited char set but one
that has the widest support. Unicode has got U+2215 and U+2044
for division and fraction composition.


 I want to be able to define / as
a path constructor and not give a flying flip that (path 2) * (path 3)
/ (path 5) - whatever the heck * might mean on paths - is not the same
as (path 2) / (path 5) * (path 3).


We need to distinguish two fundamentally different things here.
Symbol overloading which is a parser feature and operator overloading
that is runtime dispatch unless the compiler has enough information
to avoid it. Using / for paths has several drawbacks. First, it is not
the universal directory separator, \ is in widespread use also. Second,
a path is much more like a string than a number. Third, you have to
make sure that at least one of the concatenated types is a Path so that
you are dispatching to the intended implementation.

Instead of overloading ~ for paths I think inventing ~/ or ~\ as
path concatenating operators is well in line with the Perl 6 operator
set. And ~. could be the extension concatenator. And I also feel that
overloading ~ for file concatenation or photo stitching is good
practice.

BTW, operator overloading does not allow to change the precedence,
associativity and commutativity of the operator because these are
parser features.


We already had the issue of overloading / with div for Int operants.
And IIRC the conclusion then was that / is a Num operator and thus
2/3 != 0 but 2/3 == 0..



The P in Perl stands for Practical, not Pedantic.


I consider well designed interfaces as practical not pedantic ;)


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-20 Thread Mark J. Reed
On Thu, Mar 20, 2008 at 10:01 AM, TSa [EMAIL PROTECTED] wrote:
  Hmm, my idea is more about defining interfaces that allow to detach
  implementation of (numerical) algorithms from datatypes. E.g. the
  Euclidean algorithm to find the gcd requires division and a remainder
  that decreases in absolute value. This is like sorting objects that
  do the Ordered role.

Sure.  But that's different from saying Ok, you can only define an /
operator for numberish things.


   Besides, there is nothing that inherently
   associates the / symbol with division - it's only an ASCII
   approximation of fraction notation.

  We all know that ASCII is a rather limited char set but one
  that has the widest support. Unicode has got U+2215 and U+2044
  for division and fraction composition.

Not to mention good old ÷, which is even in Latin-1.

  Using / for paths has several drawbacks. First, it is not
  the universal directory separator, \ is in widespread use also.

Meh.  Even on Windows you can use / everywhere in the API, and Windows
folks are used to seeing the forward slash used this way in URLs if
nothing else.  Mac OS X uses POSIX paths under the covers, and we sure
aren't going to get the colon for this anyway...

 Second,  a path is much more like a string than a number.

Right.  Which means there's no room for confusion with division,
'cause you can't divide strings!  Ambiguity gone, problem solved, no
worries.

 Third, you have to make sure that at least one of the concatenated types is a 
 Path so that
  you are dispatching to the intended implementation.

Yes, I was sort of assuming there'd be a simple constructor for that.
Maybe even a lexically-enablable path literal syntax.  #P... anyone?
:)

  Instead of overloading ~ for paths I think inventing ~/ or ~\ as
  path concatenating operators is well in line with the Perl 6 operator
  set. And ~. could be the extension concatenator.

I would be pretty happy with ~/ and ~.  Especially if we also got
unary ~/ for making absolute paths in a natural fashion.

  And I also feel that  overloading ~ for file concatenation or photo 
 stitching is good  practice.

File concatenation, maybe; photo stitching is inherently a more
complex operation than concatenation.  Overloading ~ for that would
be, in my mind, analogous to overloading * for vectors: there's more
than one way to do that, so which operation does it mean?

  BTW, operator overloading does not allow to change the precedence,
  associativity and commutativity of the operator because these are
  parser features.

That depends on the degree to which you can munge the parser, though.
And I got the impression that in Perl6 the parser is pretty mungible.
You just have to get to it early enough...

  We already had the issue of overloading / with div for Int operants.
  And IIRC the conclusion then was that / is a Num operator and thus
  2/3 != 0 but 2/3 == 0..

What I'd really like  (blue skies, smiling at me...) to see come back
from / is a sort of abstract result-of-division object, which you can
then extract what you want out of it: quotient as float, quotient as
integer, modulus, list containing the latter two, rational fraction,
whatever.  Of course, it should automatically Numify to some default,
probably the floating point quotient, and be optimized to yield that
directly when the parser can figure out that it can do that...

   The P in Perl stands for Practical, not Pedantic.

  I consider well designed interfaces as practical not pedantic ;)

Of course, good design is extremely practical.  Just not necessarily
objectively measurable. :)

-- 
Mark J. Reed [EMAIL PROTECTED]


Re: Musings on operator overloading

2008-03-20 Thread TSa

HaloO,

Mark J. Reed wrote:

Sure.  But that's different from saying Ok, you can only define an /
operator for numberish things.


Well, if you adhere to the ring, field or whatever interface the
overloaded / sort of ends up being numberish anyway.

BTW, do we have a unary multiplikative inversion operator?
That is 1/ as prefix or **-1 as postfix? Perhaps .inv as method?
Do we have .neg for additive inversion?



Right.  Which means there's no room for confusion with division,
'cause you can't divide strings!  Ambiguity gone, problem solved, no
worries.


But without contextual information about the type of $x and $y an
expression $x/$y doesn't look particularly stringish to me.



 BTW, operator overloading does not allow to change the precedence,
 associativity and commutativity of the operator because these are
 parser features.


That depends on the degree to which you can munge the parser, though.
And I got the impression that in Perl6 the parser is pretty mungible.
You just have to get to it early enough...


But you can't mix the two concepts! Consider

  sub foo ($x)
  {
 return $x + $x * $x;
  }

and imagine a type Blahh that behaves like Num but swaps precedence
of + and *:

  my Blahh $y = 3;

  say foo($y);  # == 18
  say foo(3);   # == 12

How should the dispatcher know to dispatch to + first for $y?

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-20 Thread Larry Wall
On Thu, Mar 20, 2008 at 11:03:11AM -0400, Mark J. Reed wrote:
:Besides, there is nothing that inherently
:associates the / symbol with division - it's only an ASCII
:approximation of fraction notation.
: 
:   We all know that ASCII is a rather limited char set but one
:   that has the widest support. Unicode has got U+2215 and U+2044
:   for division and fraction composition.
: 
: Not to mention good old ÷, which is even in Latin-1.

At this point in our history, slash for division is so ingrained
into the culture that it would be very difficult to change without
widespread grumbling.  People have a hard enough time accepting things
the extra typing of «+», and I suspect we get away with that only
because the user feels the construct is very powerful, and hence
worth the agony.  Huffman coding can be tweaked in several ways,
and power / cost might be one of them.  Division is perceived as a
very basic operation, so not worth much cost to type.

Another minor psychological factor is comes into play is that, besides
being too hard to type, ÷  is visually a symmetrical operator,
while division is inherently an asymmetric operation.  You'll notice
that other asymmetric operators invented by mathematicians tend to
convey that asymmetry visually.  And even with division, the notion
of over is asymmetrical, which / is of course proxying for.

But perhaps the overriding reason to avoid ÷ is that it's perceived
as something that's only used in grade school that you grow out of.

:   Using / for paths has several drawbacks. First, it is not
:   the universal directory separator, \ is in widespread use also.
: 
: Meh.  Even on Windows you can use / everywhere in the API, and Windows
: folks are used to seeing the forward slash used this way in URLs if
: nothing else.  Mac OS X uses POSIX paths under the covers, and we sure
: aren't going to get the colon for this anyway...

Well, then there's VMS...  :)

:  Second,  a path is much more like a string than a number.
: 
: Right.  Which means there's no room for confusion with division,
: 'cause you can't divide strings!  Ambiguity gone, problem solved, no
: worries.

Er, except for hordes of Perl 5 programmers who think you can...  :)

:  Third, you have to make sure that at least one of the concatenated types is 
a Path so that
:   you are dispatching to the intended implementation.
: 
: Yes, I was sort of assuming there'd be a simple constructor for that.
: Maybe even a lexically-enablable path literal syntax.  #P... anyone?
: :)

Been trying to avoid tokens that start with # to keep the parsing rules
simple...er, less complex...  We don't even allow # for user-defined
quotes any more, since it's legal to have whitespace (and hence, a
comment) between the q and the quote char.

But I'd suggest that path() would be much more readable, and Path()
is already a built-in coercion if you have a Path type.  And how
often do you really type path literals?  And maybe it would better
be handled by some kind of url-ish string that gets mapped to the
local conditions transparently.  Or just use arrays, which are much
more convenent for directory tree traversals, and convert to path
at the last moment.

:   Instead of overloading ~ for paths I think inventing ~/ or ~\ as
:   path concatenating operators is well in line with the Perl 6 operator
:   set. And ~. could be the extension concatenator.
: 
: I would be pretty happy with ~/ and ~.  Especially if we also got
: unary ~/ for making absolute paths in a natural fashion.

Those would work, though I wouldn't exactly call 'em pretty...  Nice
visual correspondence though.  I'd even let you have ~: for the drive.  :)

:   And I also feel that  overloading ~ for file concatenation or photo 
stitching is good  practice.
: 
: File concatenation, maybe; photo stitching is inherently a more
: complex operation than concatenation.  Overloading ~ for that would
: be, in my mind, analogous to overloading * for vectors: there's more
: than one way to do that, so which operation does it mean?

At some point it becomes silly to define an operator when you can just
say mystitch(@pix).

:   BTW, operator overloading does not allow to change the precedence,
:   associativity and commutativity of the operator because these are
:   parser features.
: 
: That depends on the degree to which you can munge the parser, though.
: And I got the impression that in Perl6 the parser is pretty mungible.
: You just have to get to it early enough...

Not disagreeing with either of you, but more in the way of an
explication...

You can add or change operator syntax in Perl 6, but such changes are
mandatorily lexically scoped, as are all macros and grammatical tweaks.
It's quite possible for a given operator parser to adjust its own
precedence and associativity on the fly.  Indeed, the assignment
operator has to decide at parse-time, based on its left argument,
whether its precedence is that of an item assignment or a list
assignment.

What you guys 

Re: Musings on operator overloading

2008-03-20 Thread Larry Wall
On Thu, Mar 20, 2008 at 05:06:00PM +0100, TSa wrote:
 BTW, do we have a unary multiplikative inversion operator?
 That is 1/ as prefix or **-1 as postfix?

Well, 1/ looks like a pretty good prefix. :)

Except it's not really first class.  This ain't Haskell...

As for **-1, I'd suspect that of being more approximative
than the corresponding division on some architectures.

 Perhaps .inv as method?

I imagine most non-mathematicians would go more for .recip or some
such.

 Do we have .neg for additive inversion?

We currently have $num.prefix:- which is admittedly a bit unwieldy.

But it's difficult to extend that syntax to reciprocal, since

$num.infix:/(1)

doesn't work because the args are in the wrong order.  If someone *did*
define prefix:1/ then you could say:

$num.prefix1/

though that probably screws up precedence somehow.

 But you can't mix the two concepts!

Indeed, to the first approximation, the parser pays no attention to
the types, and multiple dispatch pays no attention to the syntax.

Larry


Re: Musings on operator overloading

2008-03-20 Thread Doug McNutt
At 17:06 +0100 3/20/08, TSa wrote:
BTW, do we have a unary multiplikative inversion operator?
That is 1/ as prefix or **-1 as postfix? Perhaps .inv as method?
Do we have .neg for additive inversion?

There certainly is the unary minus even though it is badly interpreted in some 
languages, thankfully NOT including perl 5.

Don't even think about parsing  = -$x**2; so that it returns a positive result.

Perl 5 handles it by assigning a higher precedence to ** than to addition. The 
real fact is that the minus sign in the above formula just isn't a unary minus 
in chalkboard algebra.

= $a - $b - f($x);  when $a is known to by identically equal to $b should be 
the same as
= 0 -  f($x); or just
= - f($x);  which happens easily with pencil and paper.

Don't allow it to become

= f(-$x);   ## wrong!

even if the f() is really written as $x**2 or has some other postfix operation 
- inversion -  that's considered a function by a mathematician.

*

At 15:01 +0100 3/20/08, TSa wrote:
BTW, operator overloading does not allow to change the precedence,
associativity and commutativity of the operator because these are
parser features.

A vector on the chalkboard can be a row or a column but in a computer it's an 
ordered list with the vertical or horizontal order of the components residing 
only in the mind of the programmer.

Multiplying a vector by a matrix implicitly indicates that the vector is a row. 
Multiplying a matrix by a vector implies a column vector and the results are 
quite different.

=$vector * $matrix;

is probably well handled in a overloading method because the order implies the 
rowness or columnness of the vector but it could get confused by a parser that 
has its own ideas about precedence and commutativity.

-- 

-- From the U S of A, the only socialist country that refuses to admit it. --


Re: Musings on operator overloading

2008-03-20 Thread Mark J. Reed
On Thu, Mar 20, 2008 at 1:09 PM, Doug McNutt [EMAIL PROTECTED] wrote:
  Don't even think about parsing  = -$x**2; so that it returns a positive 
 result.

Okay, going way off on a tangent here, but  I don't think the Perl
interpretation is quite as obviously correct as you think it is;
there's a reason the perlsyn page describes it as possibly surprising.
 Especially if you use a literal instead of a variable, in which case
the '-' might be considered part of the literal token in some
languages and preempt operator precedence altogether.

In any case, the decision is far from unanimous.  Fortran, the
original source of the ** operator, agrees with Perl on this front;
but COBOL, if asked to COMPUTE the same expression, returns a positive
result.  ( I know, what do you expect from a business-oriented
language...)

Ada, AWK, Groovy, Haskell, LSL, Lua, Pascal, Python, Ruby, Scala, and
Simula all agree that the result is negative.

APL also agrees, and it's arguably the ultimate mathematician's
language, but it also just evaluates right to left with no precedence
levels.  There are also languages like M[UMPS] that similarly lack
precedence and just plow through left to right, which yields a
positive answer here.

Precedenceful languages that return a positive result include
ALGOL-68, AppleScript, bash/ksh/zsh (let-arithmetic), bc(1), Eiffel,
and SNOBOL.

SmallTalk has no unary -, but 0 - x raisedTo: 2 yields a positive answer.

The various Basic implementations disagree with each other; Visual
Basic (including VB.NET) and LibertyBASIC say it's positive, while
Chipmunk says negative.  Going back in time to 8-bit days, the BASICs
on  Commodore, TI, Sinclair, and TRS-80 (model 1 level 2) machines
return a negative result, while Apple and Atari return a positive one.

I find it particularly interesting that not even all of the BASICs
from the same codebase (Microsoft's original Altair release) agree
with each other...

We now return you to your regularly scheduled Perl 6 mailing list,
already in progress.

-- 
Mark J. Reed [EMAIL PROTECTED]


Re: Musings on operator overloading (was: File-Fu overloading)

2008-03-20 Thread Aristotle Pagaltzis
Hi Jonathan,

* Jonathan Lang [EMAIL PROTECTED] [2008-02-24 22:30]:
 So if I'm understanding you correctly, the following would be
 an example of what you're talking about:
 
   { use text; if $a  49 { say $a } }
 
 ...with the result being the same as Perl5's 'if $a gt 49 {
 say $a }' (so if $a equals '5', it says '5'). Am I following
 you? If so, I'm not seeing what's so exciting about the
 concept; all it is is a package that redefines a set of
 operators for whatever scopes use it. If I'm not following you,
 I'm totally lost.

you’re indeed following me. And it’s indeed not very exciting.

And that’s exactly the point. I find that regular, type-based
overloading is *very* exciting… but not in a good way. An
approach that makes operator overloading an unexciting business
therefore seems very useful to me.

Regards,
-- 
Aristotle Pagaltzis // http://plasmasturm.org/