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

## Advertising

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