September 10, 2001 Re: Operator overloading. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Axel Kittenberger | Axel Kittenberger wrote:
>>strVal = salute :+: firstName :+: midInit :+: lastName :+:
>>perhapsComma :+: jr_etc :+: titlePunct :+: title
>>
>
> Well = will also be most like an overload assignment operator so:
>
> strVal :=: salute :+: firstName :+: midInit :+: lastName :+: perhapsComma :+: jr_etc :+: titlePunct :+: title
>
> I can already estimate that people will not be pleased to realise that
> a = b :+: c;
>
> will do something fundamently different than,
> a :=: b :+: c;
>
> This results into something error prone :/
>
|
September 10, 2001 Re: Operator overloading. (Partially) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Axel Kittenberger | Axel Kittenberger wrote:
>>strVal = salute :+: firstName :+: midInit :+: lastName :+:
>>perhapsComma :+: jr_etc :+: titlePunct :+: title
>>
>
> Well = will also be most like an overload assignment operator so:
>
> strVal :=: salute :+: firstName :+: midInit :+: lastName :+: perhapsComma :+: jr_etc :+: titlePunct :+: title
>
> I can already estimate that people will not be pleased to realise that
> a = b :+: c;
>
> will do something fundamently different than,
> a :=: b :+: c;
>
> This results into something error prone :/
>
Sorry about the empty reply.
If you don't want it to mean something "fundamentally different", then don't define it that way. You could also define append to mean something silly, but we generally suppose that you won't. And the = was inteneded to be the standard string-to-string assignment, so I didn't redefine it.
But append is only annalogous to addition, so it was appropriate to use an analogous operator, but not appropriate to re-define the original addition. Now I would admit that it was reasonable to use to + operator for all purely numeric types, providing that the implemented transitivity, commutativity, and association. This would include matricies, vectory, etc. But notice that this doesn't extend to multiplication, as the multiplication of structured numeric types doesn't obey commutativity. I.e., A * B != B * A for matricies (except in special cases.)
Similarly, string concatenation doesn't obey association:
"a" + "b" != "b" + "a"
so the simple + operation is the wrong choice. Etc.
Frequently an operation can be defined appropriately only for the classes that implement "some interface":
E.g., if Comparable is implemented then the operators:
< <= == >= > != are defineable. If a particular class implements Comparable, then all of its decentant classes should be able to use those operators (well, D doesn't seem to provide a way of hiding them). But this doesn't seem to me to mean that they should necessarily use the same ordering.
Actually, this highlights one of the weaknesses in the class inheritance structuring of programs. Frequently a praticular chunk of data, stored in a particular structure, will need to be accessed in more than one order.
For example, databases will generally use more than one index to access the data in the files. Some of these indexes (most actually) will only pull up a part of the data. So one defines views over the data.
Now imagine that the database is in memory. Probably it would be in an array, but the index would not be significant, except as a accessing method. Stepping through on the index would access all of the data in sequence, but not in any particularly useful sequence. So one would want to define several different views of the data, which would allow one to access the data in different orders (and pull up different pieces of it). Some of them would be read only views. Etc. This seems to map more easily onto structs and functions then onto classes and inheritance. And yet these aren't simple things. One would often want them to exhibit fairly complex behaviors. So one would end up implementing a class for each record type. And even fairly closely related record types would have difficulty defining an inheritance relationship that implied mixing their functionality with that of another record type. Two identical fields would be more likely to be a join key field than a field for sorting the two kinds of record on, e.g. So they typical class building operation would involve joining pieces of the two record types together into one. But this is a prohibited variety of inheritance. And in any case it would frequently be implemented by building a list of correspondences between the two record categories, and then for each funciton call on an item in the list, forwarding the call to the appropriate record type for processing.
So this view of "multiple inheritance" is a bit different than the normal programming language model. This is viewing multiple inheritance as rather like a SQL Select statement, with multiple files. And one would want the join operator to be able to work on all of the record types defined.
I seem to have veered a bit from operator overloading. My appologies. But it doesn't feel less important because of that.
|
September 10, 2001 Re: Operator overloading. (Partially) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles Hixson | > If you don't want it to mean something "fundamentally different", then don't define it that way. You could also define append to mean something silly, but we generally suppose that you won't. And the = was inteneded to be the standard string-to-string assignment, so I didn't redefine it. Well fundamentally different was a false, it's even worse than that: it's slightly different a = b; will assign the object a to point to b and to be a synonym for it in future a :=: b; will take the contents of b and assign/copy them to a; Now take folowing hypothetical code: a = b; b.printf("%d", 7); writeln(b); vs: a :=: b; b.printf("%d", 7); writeln(b); The results will be different, not the language is wrong that way, I just want to point that this way we're just creating a caveat, a hole thounds will fall into. Well supposed ten thousend people will use it :) so let's better say 25% of users. How many people debugged hour for hour again and again for write '=' in if's until compilers learned to warn there? > But append is only annalogous to addition, so it was appropriate to use an analogous operator, but not appropriate to re-define the original addition. Now I would admit that it was reasonable to use to + operator for all purely numeric types, providing that the implemented transitivity, commutativity, and association. This would include matricies, vectory, etc. But notice that this doesn't extend to multiplication, as the multiplication of structured numeric types doesn't obey commutativity. I.e., A * B != B * A for matricies (except in special cases.) > > Similarly, string concatenation doesn't obey association: > "a" + "b" != "b" + "a" > so the simple + operation is the wrong choice. Etc. Okay I agree, but an optimizer should know if an user operation is associative, or communative, or ummm. I forget now the name of the last one from a = b, and b = c follows a = c. Now you define the syntax for telling this the compiler, a checker that checks if this is true, and an optimizer that's able to handle that :o) > Now imagine that the database is in memory. Probably it would be in an array, but the index would not be significant, except as a accessing method. Stepping through on the index would access all of the data in sequence, but not in any particularly useful sequence. So one would want to define several different views of the data, which would allow one to access the data in different orders (and pull up different pieces of it). Some of them would be read only views. Etc. In example, a hashmap, right? > This seems to map more > easily onto structs and functions then onto classes and > inheritance. And yet these aren't simple things. One would > often want them to exhibit fairly complex behaviors. So one > would end up implementing a class for each record type. And > even fairly closely related record types would have difficulty > defining an inheritance relationship that implied mixing their > functionality with that of another record type. Two identical > fields would be more likely to be a join key field than a field > for sorting the two kinds of record on, e.g. So they typical > class building operation would involve joining pieces of the two > record types together into one. But this is a prohibited > variety of inheritance. And in any case it would frequently be > implemented by building a list of correspondences between the > two record categories, and then for each funciton call on an > item in the list, forwarding the call to the appropriate record > type for processing. > > So this view of "multiple inheritance" is a bit different than the normal programming language model. This is viewing multiple inheritance as rather like a SQL Select statement, with multiple files. And one would want the join operator to be able to work on all of the record types defined. Reading this, and thinking what I touched in the past, only one world hits my mind regarding this: Deplhi! Am I right? I guess many things where handled this way there like the Tables, Lists, and it's wonderfull interface to SQL. Well wasn't this why polymorphism was introduced? (virtual functions) - Axel |
September 10, 2001 Re: Operator overloading. (Partially) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Axel Kittenberger | Axel Kittenberger wrote: > ... >> Now imagine that the database is in memory. Probably it >> would be in an array, but the index would not be >> significant, except as a accessing method. Stepping >> through on the index would access all of the data in >> sequence, but not in any particularly useful sequence. >> So one would want to define several different views of >> the data, which would allow one to access the data in different >> orders (and pull up different pieces of it). Some of them >> would be read only views. Etc. >> > > In example, a hashmap, right? > A hashmap doesn't imply an ordering. I suppose that you can sort the keys, but then what's the gain in making it a hashmap rather than, say, a balanced tree, which would inherently have the order present? > .. >> So this view of "multiple inheritance" is a bit different >> than the normal programming language model. This is >> viewing multiple inheritance as rather like a SQL Select >> statement, with multiple files. And one would want the >> join operator to be able to work on all of the record >> types defined. >> > > Reading this, and thinking what I touched in the past, only > one world hits my mind regarding this: Deplhi! Am I right? > I guess many things where handled this way there like the > Tables, Lists, and it's wonderfull interface to SQL. > > Well wasn't this why polymorphism was introduced? (virtual > functions) > > - Axel > Virtual functions don't adequately handle this. Even SQL only handles a portion of it. This comes more out of databases than any programming language that I've encountered. MS Basic ends up wrapping all the data definitions into a string class that's interpreted at run time. Not a good answer. Most languages seem to just ignore the problem. Python allows one to import an external B+Tree (SleepyCatDB) with an interface that's the same as a hashtable (Dictionary) even though it is inherently sorted. It works well because a B+Tree supports random access quite well. But Python allows one to dynamically determine the members of a class. This is probably inappropriate for D, but I'm not sure what the appropriate way is. And, I notice that I'm suddenly back on the thread again. Python handles the mapping by re-defining the dictionary access operators, so that one can access the B+Tree as if it were a dictionary. There are, however, also methods that permit the definition of indicies within the database, etc. But a dictionary that gets too large, or which suddenly needs to become persistent, can be migrated to a database with only the change of a few lines in the program. |
September 11, 2001 Re: Operator overloading. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles Hixson | Charles Hixson wrote:
> b) You can be obfuscated with nearly any language feature. Just
> because some people have gone hog-wild is no reason to denigrate
> the whole concept. OTOH, I do support a clear distinction
> between user defined operators and system defined operators.
> But I also know of languages that don't support that
> disctinction, and which don't suffer excessively because of that.
Just for arguments sake, if you had distinct user defined operators,
and if we ever get some form of generic programming into the language,
how would you suggest writing generic code that could work both for
built in type like floats, and user defined type like vectors? You can
use '==' on user types, and you (presumably) can't use ':==:' (or what
ever we make) on built ins.
I'm all for overloads, and I don't mind differentiated between user
types and built in type, but I don't want use this to paint us into a
corner with regard to generic programming.
Dan
|
September 11, 2001 Re: Operator overloading. (Partially) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles Hixson | > A hashmap doesn't imply an ordering. I suppose that you can sort the keys, but then what's the gain in making it a hashmap rather than, say, a balanced tree, which would inherently have the order present?
No didn't mean sorting, but you've also two ways to access a hashmap, a) iterate through all entries without any order, b) fast-get a specifc entry by it's key.
|
September 11, 2001 Re: Operator overloading. | ||||
---|---|---|---|---|
| ||||
Posted in reply to a | a wrote:
> Charles Hixson wrote:
> ... Just for arguments sake, if you had distinct user defined operators,
> and if we ever get some form of generic programming into the language,
> how would you suggest writing generic code that could work both for
> built in type like floats, and user defined type like vectors? You can
> use '==' on user types, and you (presumably) can't use ':==:' (or what
> ever we make) on built ins.
> I'm all for overloads, and I don't mind differentiated between user
> types and built in type, but I don't want use this to paint us into a
> corner with regard to generic programming.
>
> Dan
>
One could certainly define:
operator :==: (left, right : float)
{ return (left == right); }
So I don't see that as a problem.
|
September 12, 2001 Re: Operator overloading. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles Hixson | Charles Hixson wrote:
>
> a wrote:
>
> > Charles Hixson wrote:
> > ...
> > Just for arguments sake, if you had distinct user defined operators,
> > and if we ever get some form of generic programming into the language,
> > how would you suggest writing generic code that could work both for
> > built in type like floats, and user defined type like vectors? You can
> > use '==' on user types, and you (presumably) can't use ':==:' (or what
> > ever we make) on built ins.
> > I'm all for overloads, and I don't mind differentiated between user
> > types and built in type, but I don't want use this to paint us into a
> > corner with regard to generic programming.
> >
> > Dan
> >
>
> One could certainly define:
> operator :==: (left, right : float)
> { return (left == right); }
>
> So I don't see that as a problem.
And we go from looking at (left == right) and not know if we have built
ins or object to seeing (left :==: right) and not know if we are looking
at built ins or objects. I think we have just subverted someone else's
intentions.
Dan
|
September 12, 2001 Re: Operator overloading. | ||||
---|---|---|---|---|
| ||||
Posted in reply to a | a wrote: > Charles Hixson wrote: > >> a wrote: >> >> >>> Charles Hixson wrote: ... >>>>>> >> One could certainly define: operator :==: (left, right : >> float) { return (left == right); } >> >> So I don't see that as a problem. >> > > And we go from looking at (left == right) and not know if > we have built ins or object to seeing (left :==: right) and > not know if we are looking at built ins or objects. I > think we have just subverted someone else's intentions. > > Dan > The built-in operators are still available. So that hasn't been subverted. The :==: has been defined in a way that is seen by the designer as consistent with the way he generally uses the operator, so that hasn't been subverted. I don't understand your point. Whose intentions to do what have been subverted how? |
October 29, 2001 Re: Operator overloading. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> wrote in message news:9lkiqi$2pqd$1@digitaldaemon.com... > > Russell Bornschlegel wrote in message <3B7DC29E.3415E464@estarcion.com>... > >Of course, adopting this rule leads you down a slippery slope back down to the plus sign. I'd be very happy to have you wind up at the bottom of that slippery slope and decide that C++-style operator overloading is acceptable for D. All language features are abusable; don't let the design of iostream sour you on the concept of operator overloading. > > > I admit that implementing iostream and just the way it *looks* turned me > off. > All those << and >> just rubs me the wrong way. > > >[1] I didn't like the "dummy operand" solution for ++/-- in C++, though. How about ++operator and operator++ ? > > Why not just say ++ and -- are not overloadable <g> ? If that were the case, STL iterators would be much harder to use... as normal pointers provide ++ and -- but not .inc() and .dec() or whatever. Not providing operator overloading at the time you decide to provide templates could lead to problems. Keeping an eye out for templates could be a large factor in the design of your operator overloading solution... otherwise there'd be no way to design a template that could accept either standard numeric types or user-defined types interchangeably, as the user-defined classes would end up having to use a different syntax for operators such as :+: or whatever, so the template for a + b wouldn't match operator :+:. I've written and used enough matrix and vector classes to know how valuable operator overloading is... so of course I want them in the D language. But I also want templates at some point so don't rush to conclusions about how operator overloading should work. One solution for this may be that if you specify :+:, and there's no match for the types involved for a user-redefined operator :+:, the compiler should try to apply the normal operator + instead. Same for all other operators D has built in. :*: => * , etc. Then inside templates you would always use :+:. However that will surely make templates even uglier than they would have to be already. I'd rather just be able to overload any identifier or series of symbols not allowing white space and not mixing digits or alphanumerics together with symbols, and specify whether it's infix (binary) or prefix (unary) or postfix (unary). Sure, people can misuse this. Those are the kind of things people will both praise and curse D for. For those who've been shot in the foot and are against operator overloading, I have this to say: if you can't tolerate being shot in the foot, you may be in the wrong profession. ;) Sean |
Copyright © 1999-2021 by the D Language Foundation