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/


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

2008-02-24 Thread Andy Armstrong

On 24 Feb 2008, at 15:00, Aristotle Pagaltzis wrote:

Something like

   path { $app_base_dir / $conf_dir / $foo_cfg . $cfg_ext }



I've wanted this often. I've also wanted a clean way to lexically  
supply a default target object. For example with HTML::Tiny you often  
write


 my $h = HTML::Tiny-new();
 $h-body($h-head($h-title('FooPage')), $h-body(...));

I'd love to be able to drop the '$h-' everywhere. Like this:

 $h-body( head( title( 'FooPage' ) ), body( ... ) );

I guess that would/could be a related mechanism.

--
Andy Armstrong, Hexten






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

2008-02-24 Thread Luke Palmer
On Sun, Feb 24, 2008 at 3:00 PM, Aristotle Pagaltzis [EMAIL PROTECTED] wrote:
  Something like

 path { $app_base_dir / $conf_dir / $foo_cfg . $cfg_ext }

  where the operators in that scope are overloaded irrespective of
  the types of the variables (be they plain scalar strings,
  instances of a certain class, or whatever).

This is excellent.  I've long supported the one symbol-one meaning
idea.  There are some trade-offs, though, which I'll describe.  I'll
use Haskell as my object language, since it does this sort of operator
defining rather than operator overloading (only for infix binary
operators though, not full syntactic constructs).

Recently I implemented a Vector class in Haskell.  Vectors have
addition and multiplication, of a sort, so it makes sense to use the +
and * operators.   In Haskell overloading comes in type classes, where
the operators you overload need to have specific types and you also
have an implicit contract to obey some laws about them when you
overload.  In the context of Perl, types don't mean squat, but the
implicit laws are still important, so this argument still applies.
The Num class for these operators looks like this:

  class Num a where
(+) :: a - a - a   -- take 2 arguments of type a and return 1 of type a
(*) :: a - a - a
...

Which means that if I wanted to overload (+) to work on vectors, my
(+) would have to have type Vector - Vector - Vector.  That's fine,
it is that type.  And it's associative and commutative as the class
expects.

The trouble is with (*).  There are three types of multiplication on
vectors, with these types:

Double - Vector - Vector
Vector - Double - Vector
Vector - Vector - Double  -- inner product

None of which is Vector - Vector - Vector as Num is expecting.

Now, not letting me overload (*) was a good idea on Num's part.
Normally if you have some v in Num, you can say (v*v) + v and it will
be legal.  But if v were a vector, then this wouldn't work, you'd end
up trying to add a scalar and a vector.  It's very simple, Vectors are
not Nums in the sense that the class requires

The way I solved this was to create my own class with special vector
operations, so the user of the module had to differentiate between
vector operations and scalar operations.

  class Vector v where
(^+^) :: v - v - v
(*^)  :: Double - v - v
(^*^) :: v - v - Double

  x ^* y  = y *^ x
  x ^-^ y = x ^+^ (-1) *^ y

Which could be construed as annoying.

This problem could have been ameliorated in another way, namely to
have designed Num differently.  If Num separated the notions of
addition and multiplication, or even had been designed as a Vector
space in the first place, then I could have used + and * like I wanted
to.  But it wasn't, so I couldn't.  More below.

  I hope it's obvious how such a thing would me implemented. Now,
  if you used type-bound overloading, then the following two
  expressions cannot yield the same result:

 ( 2 / 3 ) * $x
 2 * $x / 3

  But if overloading was scope-bound, they would!

And here is why you need ad-hoc overloading in addition to scope-based
overloading.  There are times when I mean 2/3  4 to mean the symbolic
data structure representing that condition, and there are other times
when I just want to check whether 2/3 is less than 4!  Here's a
contrived example:

  my $expr = 1;
  my $count = 1;
  while ($count  10) {
print $count $expr\n;
$expr = $expr + $expr;
$count = $count + 1;
  }

With the intention of printing something like:

  1 1
  2 1 + 1
  3 (1 + 1) + (1 + 1)
  ...

Which is, of course, broken.  I would have to do something crazy with scopes:

  while ($count  10) {
print $count $expr\n;
$expr = do { use Math::Symbolic; $expr + $expr };
$count = $count + 1;
  }

Which could also be construed as annoying.

However, here $count + 1 and $expr + $expr are the same +.  They both
mean add.  Why should I have to play with scopes for this.  Contrast
this with Java, where 3 + 4 and hello  + world are different +s
(unless you're used to thinking about monoids).  Getting those two to
coexist is the thing that should require playing with scopes (or
better yet, using diffrent symbols for the two of them).

I do think the best solution is a combination of overloading and
scoping.  That is, allow operator overloading, but not overloading the
name +, rather overloading a specific +, such as Math::infix:+.

This still allows poor usage as we've commonly seen with operator
overloading.  But it also allows well-behaved usage, which was
previously forbidden.

Luke


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

2008-02-24 Thread Larry Wall
On Sun, Feb 24, 2008 at 04:23:54PM +, Andy Armstrong wrote:
 I've wanted this often. I've also wanted a clean way to lexically supply a 
 default target object. For example with HTML::Tiny you often write

  my $h = HTML::Tiny-new();
  $h-body($h-head($h-title('FooPage')), $h-body(...));

 I'd love to be able to drop the '$h-' everywhere. Like this:

  $h-body( head( title( 'FooPage' ) ), body( ... ) );

 I guess that would/could be a related mechanism.

In Perl 6 you can at least get it down the minimalistic indication
of a method vs function:

given $h {
  .body( .head( .title( 'FooPage' ) ), .body( ... ) );
}

That can be construed as clean in a way that a functional interface
with an implicit object could not.  P6 is big on distinguishing
method calls from function calls *because* of wanting to distinguish
object-centric single dispatch from function-based multiple dispatch
(including all operator dispatch) which, by the way, is generally
controlled lexically in P6, as the OP suggests.  (It's also used in
the global (or more like super-lexical) Prelude scope by the compiler
to define the base language each compilation unit starts in.)
So we're ahead of you there...  :)

Basically anything that could be construed as language mutation is
limited lexically in P6, and mixing in user-defined multimethods can
be construed as at least semantic mutation, and is also syntactic
mutation if you define new operators rather than merely overloading
existing ones.  (We have a bias toward new operators for different
semantics, also suggested in the OP.  There's lots of Unicode operators
available, I hear...)

But back to .body etc.  To go further than that without the cooperation
of the class, you'd have to curry the invocant on a class, currently
described as something like:

(use HTML::Tiny).assuming(:self(HTML::Tiny.new()));

which would presumably import all the methods as functions, give
or take the fact that that syntax would not intrinsically indicate
the desire to import anything, which is a problem.  It is probably
a common enough operation to give a shortcut to:

use HTML::Tiny :singleton;

or some such, which would automatically run new, curry all the methods
on the invocant, install those resulting functions under the singleton tag
as marked for export, then import them as you would any other tag.  Then
your call reduces to:

body( head( title( 'FooPage' ) ), body( ... ) );

But as I just described it, if you wanted to use another singleton in
a different scope, you'd end up clobbering singleton tag, so really
you want to treat that as an anonymous tag somehow.  (Import tags
are really just subpackages in P6, so an anonymous temporary subpackage
is likely not a problem.)  Then you wouldn't have colliding curries,
and the exporting module doesn't have to be aware of who is importing
from it, which is pretty bogus when you think about it.

Presumably the HTML::Tiny protoobject can then be queried for its
singleton object if you really need to have $h for some reason.

Larry


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

2008-02-24 Thread Doug McNutt
At 17:30 + 2/24/08, Luke Palmer wrote:
On Sun, Feb 24, 2008 at 3:00 PM, Aristotle Pagaltzis [EMAIL PROTECTED] wrote:

And I read both very carefully and failed to understand most of it.

I use perl for physics and engineering mostly because I forgot most of my 
FORTRAN long ago and perl works everywhere.

I really want to use complex numbers, vectors, matrices, and sometimes 
quarternions. I really want to be able to define or use previously defined 
operators in a way that I learned in the 50's. I want my compiler to understand 
when I use vectors in which the components are complex numbers. I want dot and 
cross product to work. I want to be able to multiply a matrix by a vector and 
get a polite error message if I try that with impossible arguments.

What I think I learned from those two messages is that it's damnably difficult 
for a parser to figure out what I'm doing. Perhaps it just isn't worth while.

But. . .

I really don't mind informing my compiler in advance about what I want a 
variable to be treated as. Typedef {}, Dimension () and the like are no problem 
at all. I don't mind. And I think that would also apply to my scientifically 
oriented friends.

Wouldn't it make life easier for the parser to overload the * operator into a 
dot product whenever both arguments have been defined as vectors or been 
returned as vectors by a previous operation? One could even use ** for a cross 
product since raising to a vector power is unreasonable. Just recognizing the 
special use declared and passing the operation off to a required subroutine 
would be adequate. Yes. It can all be expressed in simple object-oriented 
language but all of the File::Fu stuff is unduly complicating the use in 
mathematics.

Practical Extraction and Reporting are what perl is about and I know I'm 
stretching the plan but just a bit of code that will allow, but not require, 
typedefs - er classes - of special things that cause operators to be passed to 
subroutines - er class methods - to be written could make a big difference.

Even translating ^ to pow($x,$y) would be useful to some, but I remember that 
much FORTRAN. And -2^2 is -4 (correctly?) in C on a two's complement machine.

-- 

-- Life begins at ovulation. Ladies should endeavor to get every young life 
fertilized. --


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

2008-02-24 Thread Jonathan Lang
Aristotle Pagaltzis wrote:
  And this contradiction – that being able to declare sugar is
  good, but the way that languages have permitted that so far leads
  to insanity – is what sent me thinking along the lines that there
  has to be some way to make overloading sane. And we all know that
  all is fair if you predeclare. And that led me to the flash of
  inspiration: why not make overloading a property of the source
  (lexical, early-bound) rather than of the values (temporal, late-
  bound)? And what we need to do that is a way to say this scope
  is special in that the operators herein follow rules that differ
  from the normal semantics. There you have it.

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.

-- 
Jonathan Dataweaver Lang


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

2008-02-24 Thread David Green

On 2008-Feb-24, at 2:28 pm, Jonathan Lang wrote:

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


The whole point is to be not exciting: instead of being kept on the  
edge of your seat wondering what possible meaning  has this time,  
it's right there explicitly, boringly in front on you.  As indicated,  
that has advantages and disadvantages.  In general, I tend towards  
solutions that do what human beings would do (as opposed to  
programmers, although of course that isn't always feasible).


One thing humans do, when faced with a dot product, say, is to use a  
dot; and happily, Perl 6 makes it easy to define Unicode operators so  
we don't have to overload operators that mean something else.


Something else humans do, however, is to overload symbols: e.g. /  
for a filepath separator and for division.  I'm not convinced that  
scope-based overloading is the way to go in this particular case,  
though.  It is the way to go for regexes, which overload all sorts of  
symbols that have other meanings, because regexes come in self- 
contained lumps anyway.  (Although similar overloadings are used in  
Signatures, which are another limited scope, come to think of it).


Of course, using a slash for division is a slightly ugly hack anyway,  
because typewriters didn't have the proper symbol (U+00F7).  P6 could  
use ÷ for division, and / for portable path-separation.  (Which is  
kind of tempting, at least to me; I must admit I've been pondering the  
use of / for filenames for some time.)


On the other hand, I think that in real code, it should be fairly  
obvious whether you're doing arithmetic or working with files, so  
perhaps the solution is to add unambiguous alternatives for those  
exceptional cases when you want to make it absolutely explicit:  
open($dir fs ($filename ~ $total div $count)).


(I also expect that files will be treated more consistently in P6,  
without as many issues about whether a file is a string or a handle  
or an object...)



-David