Re: Musings on operator overloading
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
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
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
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
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
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
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
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
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)
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/