www.digitalmars.com         C & C++   DMDScript  

D - Operator overloading: A way to make everybody happy?

reply "OddesE" <OddesE_XYZ hotmail.com> writes:
Ok, so one more time about operator overloading...  :)

I read all the posts about operator overloading but I'm
still a bit unsure about it...Do I want it, or don't I...

I like about operator overloading the fact that you
can add, subtract, compare or assign objects to
one another much the same way as you can with
normal primitive types.

I hate some uses of operator overloading which
seem really confusing to me. I always disliked
the way cout and cin work.

But maybe there is some middle ground?
A compromise that could make everybody happy?

Here is my idea:

Think of Java, if you know it. It contains interfaces
just like D. One of these interfaces is called Clonable.
If you want your object to be copied to another,
you implement Clonable. Now what if we could
combine these kinds of interfaces with a form of
predefined operator overloading. You would have
a few predefined interfaces:

IComparable, IAssignable, ISortable, IAddable,
ISubtractable, IMultiplyable, IDividable...you get
the idea.

D would be able to check if an object implemented
any of these interfaces and would automagically
provide the suitable operators.

I have already tried to implement something like
this in C++ and I actually got IAssignable and
IComparable to work, but when I tried to add
more I got into trouble with multiple inheritance.

Just a thought, but I think this might be a solution
that would make everybody happy!


P.S: There is another thread about templates which
contains some sort of a variation on this:
Constrained Genericity (template suggestion)

--
Stijn
OddesE_XYZ hotmail.com
http://OddesE.cjb.net
__________________________________________
Remove _XYZ from my address when replying by mail
Jan 22 2002
next sibling parent reply "Sean L. Palmer" <spalmer iname.com> writes:
That could be an easy way to deal with the syntax part of it.  Sounds
promising.  I assume the operator would just map to a "normal" looking pure
virtual function, such as Addable Add(Addable other), which could then be
overridden.

Unfortunately in D all functions are virtual, so the calling overhead will
be large, but at least it would be possible to accomplish the goal of making
a class work like a built-in type.

Sean

"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a2k8u8$fao$1 digitaldaemon.com...
 Ok, so one more time about operator overloading...  :)

 I read all the posts about operator overloading but I'm
 still a bit unsure about it...Do I want it, or don't I...

 I like about operator overloading the fact that you
 can add, subtract, compare or assign objects to
 one another much the same way as you can with
 normal primitive types.

 I hate some uses of operator overloading which
 seem really confusing to me. I always disliked
 the way cout and cin work.

 But maybe there is some middle ground?
 A compromise that could make everybody happy?

 Here is my idea:

 Think of Java, if you know it. It contains interfaces
 just like D. One of these interfaces is called Clonable.
 If you want your object to be copied to another,
 you implement Clonable. Now what if we could
 combine these kinds of interfaces with a form of
 predefined operator overloading. You would have
 a few predefined interfaces:

 IComparable, IAssignable, ISortable, IAddable,
 ISubtractable, IMultiplyable, IDividable...you get
 the idea.

 D would be able to check if an object implemented
 any of these interfaces and would automagically
 provide the suitable operators.

 I have already tried to implement something like
 this in C++ and I actually got IAssignable and
 IComparable to work, but when I tried to add
 more I got into trouble with multiple inheritance.

 Just a thought, but I think this might be a solution
 that would make everybody happy!


 P.S: There is another thread about templates which
 contains some sort of a variation on this:
 Constrained Genericity (template suggestion)

 --
 Stijn
 OddesE_XYZ hotmail.com
 http://OddesE.cjb.net
 __________________________________________
 Remove _XYZ from my address when replying by mail

Jan 22 2002
next sibling parent reply "Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:a2kevr$j2g$1 digitaldaemon.com...
 That could be an easy way to deal with the syntax part of it.  Sounds
 promising.  I assume the operator would just map to a "normal" looking

 virtual function, such as Addable Add(Addable other), which could then be
 overridden.

 Unfortunately in D all functions are virtual, so the calling overhead will
 be large, but at least it would be possible to accomplish the goal of

 a class work like a built-in type.

 Sean

It is an interesting idea. While D defines all functions to be virtual, a good optimizing compiler can de-virtualize (!) any functions which are not overridden by a derived class. This is one example where D simplifies programming and reduces errors. In my C++ work, I do this manually (then I add a derived class, forget to add "virtual", and have a subtle bug. Argh!). Since an optimizing D compiler will de-virtualize all calls it can, it can potentially have many *fewer* virtual calls than the equivalent C++ program.
Jan 22 2002
parent reply "Roberto Mariottini" <rmariottini lycosmail.com> writes:
"Walter" <walter digitalmars.com> ha scritto nel messaggio
news:a2km7g$o9f$1 digitaldaemon.com...

 While D defines all functions to be virtual, a good optimizing compiler

 de-virtualize (!) any functions which are not overridden by a derived

 This is one example where D simplifies programming and reduces errors. In

 C++ work, I do this manually (then I add a derived class, forget to add
 "virtual", and have a subtle bug. Argh!). Since an optimizing D compiler
 will de-virtualize all calls it can, it can potentially have many *fewer*
 virtual calls than the equivalent C++ program.

Here Java has a point: a 'final' class cannot be derived, so the optimizing compiler can de-virtualize all functions it can. When you try to derive from this class the compiler signal an error, so you can remove the little 'final' word and recompile safely. Ciao
Jan 23 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Roberto Mariottini" <rmariottini lycosmail.com> wrote in message
news:a2ls2g$1hvv$1 digitaldaemon.com...
 Here Java has a point: a 'final' class cannot be derived, so the

 compiler can
 de-virtualize all functions it can.
 When you try to derive from this class the compiler signal an error, so

 can remove
 the little 'final' word and recompile safely.

True, but to me that 'final' keyword is there to compensate for a weakness in the optimizer. It's unnecessary.
Jan 23 2002
parent reply "Roberto Mariottini" <rmariottini lycosmail.com> writes:
"Walter" <walter digitalmars.com> ha scritto nel messaggio
news:a2nt3r$2v4f$3 digitaldaemon.com...
 "Roberto Mariottini" <rmariottini lycosmail.com> wrote in message
 news:a2ls2g$1hvv$1 digitaldaemon.com...
 Here Java has a point: a 'final' class cannot be derived, so the

 compiler can
 de-virtualize all functions it can.
 When you try to derive from this class the compiler signal an error, so

 can remove
 the little 'final' word and recompile safely.

True, but to me that 'final' keyword is there to compensate for a weakness in the optimizer. It's unnecessary.

Ok, but this little word can work like C "register" one: - You don't need an optimizer to do easy optimization. Consider that not every compiler has a (good) optimizer, especially alpha or beta compilers ;-) - A final class can be safely optimized even in debug releases, this will ease debugging. - The average optimizer is simpler to write. - A good optimizer can optimize even non-final classes (and even ignore final ones), as you stated, and as the 'register' keyword works in C. PS: I suppose there is no 'register' keyword in D, right? Ciao
Jan 24 2002
parent "Walter" <walter digitalmars.com> writes:
"Roberto Mariottini" <rmariottini lycosmail.com> wrote in message
news:a2p5j5$qlp$1 digitaldaemon.com...
 Ok, but this little word can work like C "register" one:
  - You don't need an optimizer to do easy optimization. Consider that not
 every compiler
     has a (good) optimizer, especially alpha or beta compilers ;-)

It isn't that hard to do the final optimization. You just look to see if there are any derived classes, and if any of those derived classes override it.
  - A final class can be safely optimized even in debug releases, this will
 ease debugging.
  - The average optimizer is simpler to write.

True, but I propose to simplify the language, and am willing to put a little more burden on the compiler to get that. You can remind me that I propose that D be easy to write a compiler for, and I respond that it isn't necessary for a compiler to implement this optimization!
  - A good optimizer can optimize even non-final classes (and even ignore
 final ones), as you stated,
    and as the 'register' keyword works in C.

 PS: I suppose there is no 'register' keyword in D, right?

Correct. C compilers haven't been dependent on it for over a decade.
Jan 24 2002
prev sibling parent "OddesE" <OddesE_XYZ hotmail.com> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:a2kevr$j2g$1 digitaldaemon.com...
 That could be an easy way to deal with the syntax part of it.  Sounds
 promising.  I assume the operator would just map to a "normal" looking

 virtual function, such as Addable Add(Addable other), which could then be
 overridden.

 Unfortunately in D all functions are virtual, so the calling overhead will
 be large, but at least it would be possible to accomplish the goal of

 a class work like a built-in type.

 Sean

That is indeed exactly what I was thinking of. In my opinions there are at least three benefits to using such an approach: 1. You have a standardized way of creating "operators". If you would implement IAssignable, the operator = would work for your class. If you implement IAddable, then operator + would also work. Combining the two would automatically give you operator += as well. Because the routines are standardized, and because D would make smart combinations of routines to give you combined operators such as +=, you would have to implement less functions to support more operators and errors would be made less frequently. 2. Everyone can choose. If the interface IAddable would contain a pure virtual method Add(), this would be standard. So people can choose wheter to use Add() or +, knowing they will always be both fully supported and work exactly the same, or both of them won't be supported at all. Hell, using DML you could even allow both forms to be exchanged into one another depending on a preferences setting. 3. You can detect wheter a class supports a certain type of operator. Using RTTI you can determine if a class IS A IAddable or not. This might be *very* valuable. This could also be used to force a class to support an operator. How about: COrderedList.Insert (ISortable element) ? I also see some problems for this approach though: 1. Speed. It might be too slow to implement operator overloading this way. But I really don't know how good or bad a compiler might optimise this. I imagine it would be possible for the compiler to change obj + obj to obj.Add (obj) at compile time, but I don't know if this is in fact possible. 2. Operator 'dependencies'... Think of ISortable, it would probably have a method IsLess () or something, but it doesn't really make sense to implement that without implementing IComparable's IsEqual(). Now this problem isn't new, it is just an old problem that isn't solved. In C++ it is also possible to overload < but not ==. You could try to make ISortable inherit from IComparable, so implementing IsLess forces you to implement IsEqual too. I tried this in my C++ experiment but ran into trouble with virtual inheritance. I think that it should be possible using interfaces though... To give you more of a feeling of how it would work, I'll post some sample code. I'm typing this in my newsreader, so please forgive me my 'spelling'. :) interface IAssignable { void Assign (Object obj); void Assign (int i); void Assign (bool b); void Assign (double d); void Assign (char c); // ... It gets dull, but you get the idea // One Assign for Object's and one for // each standard type. } interface IAddable { void Add (Object obj); // ... } interface ISubtractable { void Subtract (Object obj); // ... } interface IDividable { void Divide (Object obj); // ... } interface IMutiplyable { void Multiply (Object obj); // ... } interface IComparable { bool IsEqual (Object obj); // ... } interface ISortable: IComparable { bool IsLess (Object obj); // ... } class CMyObject: IComparable { public int m_i; this (int i) {m_i = i}; bool IsEqual (Object obj) { CMyObject myObj = cast (CMyObject) obj; if (myObj == null) return false; return (this.m_i == myObj.m_i); } bool IsLess (Object obj) { CMyObject myObj = cast (CMyObject) obj; if (myObj == null) return false; return (this.m_i < myObj.m_i); } } // And how you would use it: CMyObject obj1 = new CMyObject (10); CMyObject obj2 = new CMyObject (13); if (obj1 < obj2) // Would call: // if (obj1.Less (obj2)) if (obj1 <= obj2) // Would call: // if ((obj1.Less (obj2)) || (obj1.IsEqual (obj2))) if (obj1 > obj2) // Would call: // if ((! obj1.Less (obj2)) && (! obj1.IsEqual (obj2))) if (obj1 >= obj2) // Would call: // if ((! obj1.Less (obj2))) Well that's about it. Greets! -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Jan 24 2002
prev sibling next sibling parent "Juan Carlos Arevalo Baeza" <jcab roningames.com> writes:
"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a2k8u8$fao$1 digitaldaemon.com...

 But maybe there is some middle ground?
 A compromise that could make everybody happy?

Actually, there might be.
 Think of Java, if you know it. It contains interfaces
 just like D. One of these interfaces is called Clonable.
 If you want your object to be copied to another,
 you implement Clonable. Now what if we could
 combine these kinds of interfaces with a form of
 predefined operator overloading. You would have
 a few predefined interfaces:

 IComparable, IAssignable, ISortable, IAddable,
 ISubtractable, IMultiplyable, IDividable...you get
 the idea.

 D would be able to check if an object implemented
 any of these interfaces and would automagically
 provide the suitable operators.

This is actually close to the concept of a "class" in Haskell. Haskell is a very interesting language for anyone who's into programming languages. It's designed from the ground up to be a pure functional language, which usually makes the imperative programmer queasy, but it's actually a very usable and mature language at this point. So, let me show a bit what Haskell calls classes. I'll change the syntax so as to make it more D-like or C++-like: --- typeclass Eq(a) { bool operator ==(a, a); bool operator !=(a, a); // Minimal complete defintion: // (==) or (!=) // [JCAB] These are default definitions... bool operator ==(a x, a y) { return not(x != y); } bool operator !=(a x, a y) { return not(x == y); } } --- This defines the class of all types (a is a type parameter) that have equality comparison in them. Then, you can define your own types, like a 3D vector: --- class Vector3D { float x, y, z; } --- And then (separately) give the vector the equality class: --- typeclassinstance Eq(Vector3D) { bool operator ==(Vector3D v0, Vector3D v1) { return v0.x == v1.x && v0.y == v1.y && v0.z == v1.z; } // operator != gets implemented from the default. } --- Of course, the implementation of something like this in D would follow more what Stijn was saying. In Haskell, it is assumed that polymorphic functions (and operators) like those defined in a type class like that can have an extra "hidden" parameter called the dictionary (you can assume it's like an extra virtual function table pointer) for each type class used in the implementation of the function. Type classes in Haskell can require that the type reference also implement other type classes (they call it inheritance, which it is after a fashion). The standard set of Haskell classes is: class Bounded a class Enum a class Eq a class (Fractional a) => Floating a class (Num a) => Fractional a class Functor f class (Real a, Enum a) => Integral a class Monad m class (Eq a, Show a, Eval a) => Num a class (Eq a) => Ord a class Read a class (Num a, Ord a) => Real a class (RealFrac a, Floating a) => RealFloat a class (Real a, Fractional a) => RealFrac a class Show a where => means "is required for". BTW, Haskell allows the programmer to use any sequence of symbol characters as operators, like +++ or <=|=>. And define their precedence and associativity. Salutaciones, JCAB
Jan 22 2002
prev sibling next sibling parent reply "Juarez Rudsatz" <juarez correio.com> writes:
This form could be a very good way of solving the problem for classes.
But what the main purpose of operator overloading ?

For me is defining new operations over simple types. The are not strong
meaning doing :

computer a, b, c;
a = new computer(1,2);
a = new computer(1,7);
c = a + b;

For example candidates could be
Date and Time,
Grades , Minutes, Seconds
Celsius <-> Fahrenheit
Meters <-> Foots
Kilo, Pounds, etc...
Matematic types like complex ( already added ) and so on
Geometric types
Matrix types
, and etc

How could this be done with interfaces.

"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a2k8u8$fao$1 digitaldaemon.com...
Ok, so one more time about operator overloading...  :)

I read all the posts about operator overloading but I'm
still a bit unsure about it...Do I want it, or don't I...

I like about operator overloading the fact that you
can add, subtract, compare or assign objects to
one another much the same way as you can with
normal primitive types.

I hate some uses of operator overloading which
seem really confusing to me. I always disliked
the way cout and cin work.

But maybe there is some middle ground?
A compromise that could make everybody happy?

Here is my idea:

Think of Java, if you know it. It contains interfaces
just like D. One of these interfaces is called Clonable.
If you want your object to be copied to another,
you implement Clonable. Now what if we could
combine these kinds of interfaces with a form of
predefined operator overloading. You would have
a few predefined interfaces:

IComparable, IAssignable, ISortable, IAddable,
ISubtractable, IMultiplyable, IDividable...you get
the idea.

D would be able to check if an object implemented
any of these interfaces and would automagically
provide the suitable operators.

I have already tried to implement something like
this in C++ and I actually got IAssignable and
IComparable to work, but when I tried to add
more I got into trouble with multiple inheritance.

Just a thought, but I think this might be a solution
that would make everybody happy!


P.S: There is another thread about templates which
contains some sort of a variation on this:
Constrained Genericity (template suggestion)

--
Stijn
OddesE_XYZ hotmail.com
http://OddesE.cjb.net
__________________________________________
Remove _XYZ from my address when replying by mail
Jan 25 2002
next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Override Add(Object), and add an in-contract that the class be of type
computer:



class computer : IAddable
{
    Object Add(Object other)
    in
    {
        assert(other.class == computer);
    }
    body
    {
        ....
    }
}



The compiler can optimize out the vast majority of cases, where it knows
that the 2nd argument is of class computer.  If you pass something else, it
can alert user at compile time: "error: argument passed to
computer.Add(Object) breaks in-contract."  For the few cases where the
compiler can't know ahead of time, you do a trivial runtime check and throw
a BrokenContractException (or whatever) if needed.



Juarez Rudsatz wrote:

 This form could be a very good way of solving the problem for classes.
 But what the main purpose of operator overloading ?

 For me is defining new operations over simple types. The are not strong
 meaning doing :

 computer a, b, c;
 a = new computer(1,2);
 a = new computer(1,7);
 c = a + b;

 How could this be done with interfaces.

-- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Jan 25 2002
prev sibling parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"Juarez Rudsatz" <juarez correio.com> wrote in message
news:a2rqhr$1oln$1 digitaldaemon.com...
 This form could be a very good way of solving the problem for classes.
 But what the main purpose of operator overloading ?

 For me is defining new operations over simple types. The are not strong
 meaning doing :

It is not possible to overload operators for basic types, at least not in C++ or any other language I know.
 computer a, b, c;
 a = new computer(1,2);
 a = new computer(1,7);
 c = a + b;

 For example candidates could be
 Date and Time,

Date and Time are usually implemented as doubles or something, so you can add and subtract them using normal operators. No need for overloading.
 Grades , Minutes, Seconds
 Celsius <-> Fahrenheit
 Meters <-> Foots
 Kilo, Pounds, etc...

Same here, depending on the implementation, these are usually implemented as doubles or ints. No need to do any overloading, you can simply add them.
 Matematic types like complex ( already added ) and so on

 Geometric types

You mean point etc? Define a class.
 Matrix types

You wil need a class.
 , and etc

 How could this be done with interfaces.

Define a class, then implement the interfaces for the operator you need. -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Jan 25 2002
parent reply "Sean L. Palmer" <spalmer iname.com> writes:
"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a2san3$1spl$1 digitaldaemon.com...
 Geometric types

You mean point etc? Define a class.
 Matrix types

You wil need a class.
 , and etc

 How could this be done with interfaces.

Define a class, then implement the interfaces for the operator you need.

Unfortunately to provide an interface, you need a vtable. But most of the uses I find for operator overloading can't tolerate that kind of extra baggage. Vectors and Matrices, for example. A struct in D could work, but structs can't provide interfaces. I personally would be ok with operator overloading only being available for structs, not classes, but I'm not likely to get even that. ;( Maybe Walter will generalize the complex type enough that it can be turned into a useful 3 or 4 component vector. In 3d graphics we don't generally need double precision (though it could be useful in some situations). We can make arrays of 3 or 4 of those into matrices on our own, and I wouldn't mind having to use functions on just matrices. But vector math needs operator syntax in a bad way. If I can just get Walter to provide this type natively I'd be extremely happy (hopefully one of these days it could be optimized for SIMD processors too) type vector4 float& operator [0..3] float& .x , .y , .z , .w // these accessors would be nice vector4 operator + ( vector4,vector4 ) // add components vector4 operator - ( vector4,vector4 ) vector4 operator * ( vector4,vector4 ) vector4 operator * ( vector4,float ) vector4& operator += ( vector4 ) vector4& operator -= ( vector4 ) vector4& operator *= ( vector4 ) vector4& operator *= ( float ) float .length intrinsic float dot(vector4, vector4) But it'd probably be nice to have vector2 and vector3 also. int flavors could be nice too and could use probably 2,3,4, or 8 elements. Alot of processors have register types like this, but the nice thing about it is that it can all be emulated on the main FPU if necessary. It's pretty lightweight, I doubt it's hard to implement (no harder than the complex type, anyway) and people that don't need it can ignore it. People that do need it will be pleased. ;) Sean
 --
 Stijn

Jan 26 2002
next sibling parent "Robert W. Cunningham" <rwc_2001 yahoo.com> writes:
"Sean L. Palmer" wrote:

 ...
 Maybe Walter will generalize the complex type enough that it can be turned
 into a useful 3 or 4 component vector.  In 3d graphics we don't generally
 need double precision (though it could be useful in some situations).  We
 can make arrays of 3 or 4 of those into matrices on our own, and I wouldn't
 mind having to use functions on just matrices.  But vector math needs
 operator syntax in a bad way.

 If I can just get Walter to provide this type natively I'd be extremely
 happy (hopefully one of these days it could be optimized for SIMD processors
 too)

 type vector4
    float& operator [0..3]
    float&  .x , .y , .z , .w     // these accessors would be nice
    vector4 operator +  ( vector4,vector4 ) // add components
    vector4 operator - ( vector4,vector4 )
    vector4 operator * ( vector4,vector4 )
    vector4 operator * ( vector4,float )
    vector4& operator += ( vector4 )
    vector4& operator -= ( vector4 )
    vector4& operator *= ( vector4 )
    vector4& operator *= ( float )
    float .length

 intrinsic float dot(vector4, vector4)

 But it'd probably be nice to have vector2 and vector3 also.  int flavors
 could be nice too and could use probably 2,3,4, or 8 elements.

 Alot of processors have register types like this, but the nice thing about
 it is that it can all be emulated on the main FPU if necessary.  It's pretty
 lightweight, I doubt it's hard to implement (no harder than the complex
 type, anyway) and people that don't need it can ignore it.  People that do
 need it will be pleased.   ;)

 Sean

I do lots of image processing (especially color space conversions and multispectral interpolations), and I presently make use of the free (as in Beer) Intel libraries. <drool> If D were to offer vectors as Sean proposes, then the possibility of obtaining screaming native language performance for image processing without the overhead of library calls would exist. </drool> Maybe as a future language extension? -BobC
Jan 26 2002
prev sibling next sibling parent Russell Borogove <kaleja estarcion.com> writes:
Sean L. Palmer wrote:

 "OddesE" <OddesE_XYZ hotmail.com> wrote in message
 news:a2san3$1spl$1 digitaldaemon.com...
 I personally would be ok with operator overloading only being available for
 structs, not classes, but I'm not likely to get even that.  ;(
 
 Maybe Walter will generalize the complex type enough that it can be turned
 into a useful 3 or 4 component vector.  In 3d graphics we don't generally
 need double precision (though it could be useful in some situations).  We
 can make arrays of 3 or 4 of those into matrices on our own, and I wouldn't
 mind having to use functions on just matrices.  But vector math needs
 operator syntax in a bad way.

While my needs are the same as yours, and float 4-element vectors and float 4x4-element matrices would cover it, the astrophysicists will laugh at our puny 23-bit mantissas and ask where the hell the vectors of double and extended are. Apart from the SIMD issues, though, the fatter vectors should be mostly a cut-and-paste operation on Walter's part. I do agree that the vector that fits in the CPU's SIMD registers (4x32-bit float in most cases) is the most important one to offer, though. -Russell B
Jan 26 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
I've been thinking a lot about operator overloading.

1) The idea of 'special' operators for overloading, like :+: being the
overloadable version of +, is a good idea, but it fails when used with
templates.

2) Overloaded operator functions should be inlineable, which lets out
interfaces.

3) I just don't like the idea of operator functions having hidden arguments:

    int operator+(int y);

A binary operator function should, gosh darn it, have TWO operands:

    static int operator+(Foo x, int y);

4) I don't see a point to smart pointers and such in a garbage collected
language. Overloadable operators should be restricted to arithmetic
operators.

5) Operator overloading should only be used to provide arithmetic operations
on user defined arithmetic types. None of that << and >> for iostreams. I
know many people like that, but a shift is not a stream operation. It just
isn't.

6) I see no way to have the compiler enforce (5). Anyone caught violating
(5) should be forced to carry the Stone of Shame.

7) Note (3) means no virtual operator functions. To do that, you'd need:
    static int operator+(Foo x, int y)
    {
        return x.myadd(y);
    }
so no great loss.

8) If there are to be conversion operators, they will not participate in
implicit conversions, only explicit ones.

None of this is implemented or specified yet, it's just some thoughts.
Feb 12 2002
next sibling parent "D" <s_nudds hotmail.com> writes:
Walter <walter digitalmars.com> wrote in message
news:a4aril$ue9$2 digitaldaemon.com...
 I've been thinking a lot about operator overloading.

 1) The idea of 'special' operators for overloading, like :+: being the
 overloadable version of +, is a good idea, but it fails when used with
 templates.

Why?
 2) Overloaded operator functions should be inlineable, which lets out
 interfaces.

In the best of all worlds yes. But that is a limitation of the object paradigm, not operator notation. The fact is, without new operators, the user is going to be forced to perform the same operations with standard function calls anyhow. So functionally there is no substantive difference.
 3) I just don't like the idea of operator functions having hidden

     int operator+(int y);

I've never understood why this is a requirement. Use a dummy argument similar to "this" in such cases.
 4) I don't see a point to smart pointers and such in a garbage collected
 language. Overloadable operators should be restricted to arithmetic
 operators.

I disagree. Restricting them would cause people to look for ways around the restrictions, and would also limit their usefulness in abstract logical systems.
 5) Operator overloading should only be used to provide arithmetic

 on user defined arithmetic types. None of that << and >> for iostreams. I
 know many people like that, but a shift is not a stream operation. It just
 isn't.

Shift operators are used for IO streams because there is no facility for creating new operators.with arbitrary names.
 8) If there are to be conversion operators, they will not participate in
 implicit conversions, only explicit ones.

All converstions should be explicit anyhow. Implicit conversion promotes error.
Feb 12 2002
prev sibling next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a4aril$ue9$2 digitaldaemon.com...

 I've been thinking a lot about operator overloading.

 1) The idea of 'special' operators for overloading, like :+: being the
 overloadable version of +, is a good idea, but it fails when used with
 templates.

I think that most people here would be happy to be able to overload just the built-in operators... adding custom ones is quite a lot of work, and the result doesn't worth it (IMO).
 3) I just don't like the idea of operator functions having hidden

     int operator+(int y);

 A binary operator function should, gosh darn it, have TWO operands:

     static int operator+(Foo x, int y);

Agreed. Operators should only be declared outside of classes.
 4) I don't see a point to smart pointers and such in a garbage collected
 language. Overloadable operators should be restricted to arithmetic
 operators.

I suppose you mean binary + - * / & | ^ ~ and unary ++ -- ~ ! and all the op= operators? The question is, should logical operators be overloaded?
 5) Operator overloading should only be used to provide arithmetic

 on user defined arithmetic types. None of that << and >> for iostreams. I
 know many people like that, but a shift is not a stream operation. It just
 isn't.

 6) I see no way to have the compiler enforce (5). Anyone caught violating
 (5) should be forced to carry the Stone of Shame.

Yep, right. There's no way to check how operators are used. Smart guys won't do that. Those who do... it's their problems =)
 7) Note (3) means no virtual operator functions. To do that, you'd need:
     static int operator+(Foo x, int y)
     {
         return x.myadd(y);
     }
 so no great loss.

Absolutely.
 8) If there are to be conversion operators, they will not participate in
 implicit conversions, only explicit ones.

Which really kills the idea. It's simplier to have the conversion function then, toInt()/toDouble()/toString() etc.
 None of this is implemented or specified yet, it's just some thoughts.

<<< waiting patiently >>>
Feb 12 2002
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel Minayev wrote:

 4) I don't see a point to smart pointers and such in a garbage collected
 language. Overloadable operators should be restricted to arithmetic
 operators.

I suppose you mean binary + - * / & | ^ ~ and unary ++ -- ~ ! and all the op= operators? The question is, should logical operators be overloaded?

I would like to see the compiler provide the remaining logical operators if only a few are defined. That is, if you define operator==(Foo,int); and operator<(Foo,int); (or any other combination of equality and inequality operators) the compiler should be able to provide the rest. Of course, it won't always be 100% optimized...but if it's not, you can provide the rest of the operators yourself. I just always hated having to have 4 extra useless functions just to define != <= >= and > for every class. -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Feb 12 2002
next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C690E8D.37852B1 deming-os.org...

 The question is, should logical operators be overloaded?


I meant && and ||.
 I would like to see the compiler provide the remaining logical operators

 a few are defined.  That is, if you define

 operator==(Foo,int);
     and
 operator<(Foo,int);

 (or any other combination of equality and inequality operators) the

 should be able to provide the rest.  Of course, it won't always be 100%
 optimized...but if it's not, you can provide the rest of the operators
 yourself.  I just always hated having to have 4 extra useless functions

 define !=  <=  >= and > for every class.

Yes, like in C#. The same should, IMO, apply to ++, -- and op= - you can supply them if you want, but if you don't, they are generated automatically from +, - and op.
Feb 12 2002
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel Minayev wrote:

 "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
 news:3C690E8D.37852B1 deming-os.org...

 The question is, should logical operators be overloaded?


I meant && and ||.

Oh :)
 Yes, like in C#. The same should, IMO, apply to ++, -- and op= - you
 can supply them if you want, but if you don't, they are generated
 automatically from +, - and op.

True. Many of the common operators can be generated from each other. I think that you should be able to supply just a few of them and have the complier automatically provide implementations for the rest. For instance, a-b can be redone as a+(-b), which in most cases is not the optimal solution performance-wise, but it allows rapid development of simple classes. You should be able to do it in many different ways, as well. Sometimes it's easiest to provide = and +, other times it's easiest (and often more efficient) to provide = and +=. The compiler should provide the missing operators if it can. Walter, I know that this means some extra complexity for you, but I would guess that it wouldn't be *too* bad. Each operator can have a library of available automatic implementations...depending on which operators are provided by the programmer, the compiler drops in pretty standard code for each. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Feb 12 2002
parent "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C694E30.7FE96594 deming-os.org...

 True.  Many of the common operators can be generated from each other.  I

 that you should be able to supply just a few of them and have the complier
 automatically provide implementations for the rest.  For instance, a-b can

 redone as a+(-b), which in most cases is not the optimal solution
 performance-wise, but it allows rapid development of simple classes.

This might not be a good idea - not so obvious to many people =) It is clear that + can be used to implement += and ++. But a+(-b) just doesn't fit sometimes...
Feb 12 2002
prev sibling next sibling parent reply "Walter" <walter digitalmars.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C690E8D.37852B1 deming-os.org...
 I would like to see the compiler provide the remaining logical operators

 a few are defined.  That is, if you define

 operator==(Foo,int);
     and
 operator<(Foo,int);

 (or any other combination of equality and inequality operators) the

 should be able to provide the rest.  Of course, it won't always be 100%
 optimized...but if it's not, you can provide the rest of the operators
 yourself.  I just always hated having to have 4 extra useless functions

 define !=  <=  >= and > for every class.

If just a cmp() was provided, that can be used for all the comparisons.
Feb 12 2002
next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a4bm6j$1a5o$2 digitaldaemon.com...

 If just a cmp() was provided, that can be used for all the comparisons.

Hmmm... operator cmp? enum Relation { Less, Equal, Greater } // builtin Relation operator cmp(vector a, vector b) { ... }
Feb 12 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a4bqaq$1buk$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:a4bm6j$1a5o$2 digitaldaemon.com...

 If just a cmp() was provided, that can be used for all the comparisons.

Hmmm... operator cmp? enum Relation { Less, Equal, Greater } // builtin Relation operator cmp(vector a, vector b) { ... }

No, it would return an int <0, 0, or >0. That makes it more efficiently implementable.
Feb 13 2002
parent "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a4d8gg$1ult$3 digitaldaemon.com...

 No, it would return an int <0, 0, or >0. That makes it more efficiently
 implementable.

Either way, it'd make things simplier in many cases. Provide cmp, and other comparison ops are already there...
Feb 13 2002
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter wrote:

 If just a cmp() was provided, that can be used for all the comparisons.

True, but that is only for things that are reasonably ordered. Some things may have a property of equality/inequality but not ordering. In that case, you want to supply == and != but not < > <= >= Think (literally) apples and oranges :) -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Feb 12 2002
next sibling parent "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6979F9.D014E2C8 deming-os.org...

 True, but that is only for things that are reasonably ordered.  Some

 may have a property of equality/inequality but not ordering.  In that

 you want to supply == and != but not < > <= >=

That's why I suggest the special "operator cmp".
Feb 12 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6979F9.D014E2C8 deming-os.org...
 Walter wrote:

 If just a cmp() was provided, that can be used for all the comparisons.

True, but that is only for things that are reasonably ordered. Some

 may have a property of equality/inequality but not ordering.  In that

 you want to supply == and != but not < > <= >=

 Think (literally) apples and oranges :)

Object.cmp() exists already, and I figure just use that. And everyone knows that apples come before oranges <g>.
Feb 13 2002
parent "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a4d8gh$1ult$4 digitaldaemon.com...

 Object.cmp() exists already, and I figure just use that. And everyone

 that apples come before oranges <g>.

You mean that operators can only be overloaded for Objects? Not even structs?
Feb 13 2002
prev sibling next sibling parent "Sean L. Palmer" <spalmer iname.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C690E8D.37852B1 deming-os.org...
 Pavel Minayev wrote:

 4) I don't see a point to smart pointers and such in a garbage



 language. Overloadable operators should be restricted to arithmetic
 operators.

I suppose you mean binary + - * / & | ^ ~ and unary ++ -- ~ ! and all the op= operators? The question is, should logical operators be overloaded?

I would like to see the compiler provide the remaining logical operators

 a few are defined.  That is, if you define

 operator==(Foo,int);
     and
 operator<(Foo,int);

 (or any other combination of equality and inequality operators) the

 should be able to provide the rest.  Of course, it won't always be 100%
 optimized...but if it's not, you can provide the rest of the operators
 yourself.  I just always hated having to have 4 extra useless functions

 define !=  <=  >= and > for every class.

YES!!! GOD, YES!! Sean
Feb 12 2002
prev sibling parent "Roberto Mariottini" <rmariottini lycosmail.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> ha scritto nel messaggio
news:3C690E8D.37852B1 deming-os.org...
 Pavel Minayev wrote:

 4) I don't see a point to smart pointers and such in a garbage



 language. Overloadable operators should be restricted to arithmetic
 operators.

I suppose you mean binary + - * / & | ^ ~ and unary ++ -- ~ ! and all the op= operators? The question is, should logical operators be overloaded?

I would like to see the compiler provide the remaining logical operators

 a few are defined.  That is, if you define

 operator==(Foo,int);
     and
 operator<(Foo,int);

 (or any other combination of equality and inequality operators) the

 should be able to provide the rest.  Of course, it won't always be 100%
 optimized...but if it's not, you can provide the rest of the operators
 yourself.  I just always hated having to have 4 extra useless functions

 define !=  <=  >= and > for every class.

In my classes I often use as example the operator <= (_the_ order operator for mathematics): all other comparisons can be made with this (if the order is total). In C++: bool operator <=(MyClass a, MyClass b) { ... implement this } // theese are "automatic" inline bool operator == (MyClass a, MyClass b) { return (a <= b) && (b <= a); } inline bool operator < (MyClass a, MyClass b) { return (a <= b) && !(a == b); } // theese are simplicistic inline bool operator != (MyClass a, MyClass b) { return !(a == b); } inline bool operator > (MyClass a, MyClass b) { return !(a <= b); } inline bool operator >= (MyClass a, MyClass b) { return !(a < b); } OK, this work if the order is total, so (a<=b) && (b <= a) implies a == b . Ciao
Feb 13 2002
prev sibling next sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Hmmm....D beat me to the punch.  But there's a chance for intelligent
conversation yet!

Walter wrote:

 I've been thinking a lot about operator overloading.

 1) The idea of 'special' operators for overloading, like :+: being the
 overloadable version of +, is a good idea, but it fails when used with
 templates.

Are you suggesting that a special operator (like :+:) would always be associated with the related operator function operator+ ? While I personally like having the same operators, I think this might be an excellent balance...it makes it clear that the operator is not a compiler operator, but it allows an inline syntax. We still have to deal with the issues of things like dot-product vs. cross-product in vectors. What if we used the same syntax for inline function names? Basically, if you defined a function name with 2 arguments, you could call it as func(arg1,arg2) or arg1 :func: arg2. Similarly, for those for whom a trailing unary operator is useful (like factorial), you could call a single-function argument with similary syntax arg :unary-func: Each of these syntaxes would be EXACTLY equivalent to the old C function call syntax, func(arg1,arg2) and unary-func(arg), respectively. class Vector { static Vector cp(Vector a,Vector b); static double dp(Vector a,Vector b); } long fact(int i); Vector foo,bar; ... double d = a :dp: b; Vector baz = a :cp: b; long fred = 6 :fact: ; It's not pretty, but it allows an inline syntax of a sort without allowing wild creation of unlimited functions.
 2) Overloaded operator functions should be inlineable, which lets out
 interfaces.

I'm uncomfortable about this (losing interfaces) in general, but I'm not totally sure why. I would desire some more details about why interfaces get in the way.
 3) I just don't like the idea of operator functions having hidden arguments:

     int operator+(int y);

 A binary operator function should, gosh darn it, have TWO operands:

     static int operator+(Foo x, int y);

It would sure make overloading the other way around (int + Foo) easier.
 5) Operator overloading should only be used to provide arithmetic operations
 on user defined arithmetic types. None of that << and >> for iostreams. I
 know many people like that, but a shift is not a stream operation. It just
 isn't.

No reason that ALL operators have to be overridable right now. You could stick to the basic operators and add support for stuff like << and >> if people show great desire to use them.
 8) If there are to be conversion operators, they will not participate in
 implicit conversions, only explicit ones.

I agree :) -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Feb 12 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C690DAF.995AB2CB deming-os.org...
 1) The idea of 'special' operators for overloading, like :+: being the
 overloadable version of +, is a good idea, but it fails when used with
 templates.


 with the related operator function operator+   ?   While I personally like
 having the same operators, I think this might be an excellent balance...it

 it clear that the operator is not a compiler operator, but it allows an

 syntax.

The trouble is you couldn't write a template that could be instantiated for both builtin types and user defined types.
 We still have to deal with the issues of things like dot-product vs.
 cross-product in vectors.  What if we used the same syntax for inline

 names?  Basically, if you defined a function name with 2 arguments, you

 call it as func(arg1,arg2)   or    arg1 :func: arg2.  Similarly, for those

 whom a trailing unary operator is useful (like factorial), you could call

 single-function argument with similary syntax     arg :unary-func:    Each

 these syntaxes would be EXACTLY equivalent to the old C function call

 func(arg1,arg2)    and   unary-func(arg),  respectively.

 class Vector {
     static Vector cp(Vector a,Vector b);
     static double dp(Vector a,Vector b);
 }

 long fact(int i);

 Vector foo,bar;
 ...
 double d = a :dp: b;
 Vector baz = a :cp: b;
 long fred = 6 :fact: ;

 It's not pretty, but it allows an inline syntax of a sort without allowing

 creation of unlimited functions.

Perhaps this could be in a future version of D, but let's defer that for now.
 2) Overloaded operator functions should be inlineable, which lets out
 interfaces.

I'm uncomfortable about this (losing interfaces) in general, but I'm not

 sure why.  I would desire some more details about why interfaces get in

I just don't see any advantage to using interfaces for this, and an interface requires a vptr.
Feb 12 2002
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter wrote:

 The trouble is you couldn't write a template that could be instantiated for
 both builtin types and user defined types.

You could simply define that for built-in types :+: is exactly equivalent to + Or am I missing the point here?
 Perhaps this could be in a future version of D, but let's defer that for
 now.

ok. It's nice to think that the language isn't static, and that we have the time to slowly learn what the truly useful features are! :) -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Feb 12 2002
next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C697B1B.1B10E356 deming-os.org...

 You could simply define that for built-in types :+: is exactly equivalent

 +    Or am I missing the point here?

What about the ":+-*/:" operator, then? =)
Feb 12 2002
parent reply "Roberto Mariottini" <rmariottini lycosmail.com> writes:
"Pavel Minayev" <evilone omen.ru> ha scritto nel messaggio
news:a4c0oi$1efk$1 digitaldaemon.com...
 "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
 news:3C697B1B.1B10E356 deming-os.org...

 You could simply define that for built-in types :+: is exactly


 to
 +    Or am I missing the point here?

What about the ":+-*/:" operator, then? =)

I think you're missing the point. They are talking about needing a lexical sign when using an overloaded operator. So, in this view, every operator can be overloaded, but you must write something like :operator: (or something else) to state lexically that you are using an overloaded operator. No new operators can be "created" on the fly in this schema. Ciao
Feb 13 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Roberto Mariottini" <rmariottini lycosmail.com> wrote in message
news:a4do8b$279j$1 digitaldaemon.com...

 I think you're missing the point. They are talking about needing a lexical
 sign when
 using an overloaded operator. So, in this view, every operator can be
 overloaded,
 but you must write something like :operator: (or something else) to state
 lexically
 that you are using an overloaded operator.
 No new operators can be "created" on the fly in this schema.

Then I don't see much reason in adding something to state an overloaded operator explicitly. In most cases, I don't really care. I use + to add vectors just as I would add ints, and I'm pretty happy with that. If it is built-in, fine. If it is provided by some module, I should be able to use it as if it was built-in. Just my POV...
Feb 13 2002
parent "OddesE" <OddesE_XYZ hotmail.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a4dutu$2avp$1 digitaldaemon.com...
 "Roberto Mariottini" <rmariottini lycosmail.com> wrote in message
 news:a4do8b$279j$1 digitaldaemon.com...

 I think you're missing the point. They are talking about needing a


 sign when
 using an overloaded operator. So, in this view, every operator can be
 overloaded,
 but you must write something like :operator: (or something else) to


 lexically
 that you are using an overloaded operator.
 No new operators can be "created" on the fly in this schema.

Then I don't see much reason in adding something to state an overloaded operator explicitly. In most cases, I don't really care. I use + to add vectors just as I would add ints, and I'm pretty happy with that. If it is built-in, fine. If it is provided by some module, I should be able to use it as if it was built-in. Just my POV...

Totally agreed. If the lexical sign was standard, like it was *always* :op:, I could live with it. I wouldn't like it however, it just looks confusing.
Feb 16 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C697B1B.1B10E356 deming-os.org...
 Walter wrote:
 The trouble is you couldn't write a template that could be instantiated


 both builtin types and user defined types.


 +    Or am I missing the point here?
 Perhaps this could be in a future version of D, but let's defer that for
 now.


 time to slowly learn what the truly useful features are! :)

If there are too many features, we're back in the same boat as C++!
Feb 12 2002
parent "Robert W. Cunningham" <rwc_2001 yahoo.com> writes:
Walter wrote:

 If there are too many features, we're back in the same boat as C++!

Umm, we could go straight for "D++", couldn't we? (And no, I'm under no illusions of who "we" refers to.) -BobC
Feb 12 2002
prev sibling next sibling parent reply "Sean L. Palmer" <spalmer iname.com> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a4aril$ue9$2 digitaldaemon.com...
 I've been thinking a lot about operator overloading.

 1) The idea of 'special' operators for overloading, like :+: being the
 overloadable version of +, is a good idea, but it fails when used with
 templates.

Right. One of the beauties of templates is being able to write T a = b + c; when you don't even know what class b and c are, so long as it provides operator = and operator +, it'll compile.
 2) Overloaded operator functions should be inlineable, which lets out
 interfaces.

Right. When you need operator overloading you usually can't afford a virtual function call.
 3) I just don't like the idea of operator functions having hidden

     int operator+(int y);

 A binary operator function should, gosh darn it, have TWO operands:

     static int operator+(Foo x, int y);

I agree. It should be explicit. I also can't see why you shouldn't be able to override operators using only basic types. So what if I want to implement <<= for floats? Let me.
 4) I don't see a point to smart pointers and such in a garbage collected
 language. Overloadable operators should be restricted to arithmetic
 operators.

With smart pointers it's not just about refcounting... You can also restrict the pointer from being incremented or changed (prevents bugs when returning a pointer to just one thing, such as a global singleton). You can use them as accessors (if you want to talk to object X, you have to get a lock first... so obtaining one of these XAccessor objects which are smart pointers into X, automatically locks the X, and is the only way for outside code to use X, since all its methods are private to everything but the XAccessor, which forwards calls to it).
 5) Operator overloading should only be used to provide arithmetic

 on user defined arithmetic types. None of that << and >> for iostreams. I
 know many people like that, but a shift is not a stream operation. It just
 isn't.

I could live with that.
 6) I see no way to have the compiler enforce (5). Anyone caught violating
 (5) should be forced to carry the Stone of Shame.

 7) Note (3) means no virtual operator functions. To do that, you'd need:
     static int operator+(Foo x, int y)
     {
         return x.myadd(y);
     }
 so no great loss.

 8) If there are to be conversion operators, they will not participate in
 implicit conversions, only explicit ones.

Also tolerable.
 None of this is implemented or specified yet, it's just some thoughts.

Glad to see you're thinking about it. Sean
Feb 12 2002
parent "Pavel Minayev" <evilone omen.ru> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:a4bq9a$1buc$1 digitaldaemon.com...

 With smart pointers it's not just about refcounting... You can also

 the pointer from being incremented or changed (prevents bugs when

 a pointer to just one thing, such as a global singleton).  You can use

 as accessors (if you want to talk to object X, you have to get a lock
 first... so obtaining one of these XAccessor objects which are smart
 pointers into X, automatically locks the X, and is the only way for

 code to use X, since all its methods are private to everything but the
 XAccessor, which forwards calls to it).

Oh yes, and there are also iterators - kinda pointers as well =)
 None of this is implemented or specified yet, it's just some thoughts.

Glad to see you're thinking about it.

With operator overloading and templates, D would easily beat both C++ and C#, for sure. =)
Feb 12 2002
prev sibling parent "Robert W. Cunningham" <rwc_2001 yahoo.com> writes:
Walter wrote:

 I've been thinking a lot about operator overloading.

 1) The idea of 'special' operators for overloading, like :+: being the
 overloadable version of +, is a good idea, but it fails when used with
 templates.

 2) Overloaded operator functions should be inlineable, which lets out
 interfaces.

 3) I just don't like the idea of operator functions having hidden arguments:

     int operator+(int y);

 A binary operator function should, gosh darn it, have TWO operands:

     static int operator+(Foo x, int y);

I prefer declaring a new or overloaded operator to EXACTLY resemble a function declaration. Where, buy default, most functions are "prefix" (the function name comes first, followed by arguments), operators can be infix (function name between arguments, arguments limited to exactly two) or even postfix (function name follows all arguments). Let's allow for the whole gamut! M4 is smart enough to handle such notation, and I've used it with several languages where I was desperate to use non-prefix function call notations. In the following, please excuse my use of caps and long names: I do not advocate their use as-is, but I want to make it clear what I'm doing. So, given the following: int foo( int, int) {...}; and int x = foo(1,2); We could easily have: INFIX_OPERATOR int foo(IN int, IN int) {...}; and x = 1 foo 2; Or even this: INFIX_OPERATOR myType +(IN myType, IN myType) {...}; and myType x, y, z; ... x = y + z; IMO, the context makes the intent clear and easily parseable. Now, let's talk about our favorite C feature, assignment operators. Can we declare those as well? Let's try: ASSIGNMENT_OPERATOR myType +=(IN OUT myType, IN myType) {...}; The ASSIGNMENT_OPERATOR is similar to INFIX_OPERATOR, except that the first parameter must be an IN OUT parameter. This notation would also allow: myType a, b, c, d; d += a += c += b; Yes, of course, assignments are valid on the right hand side. To preclude this behavior, you'd need to define the function as returning void. Then the above statement would issue a type error for all assignments before the last one. (Strange, but true...) I see no need for any explicit "overload" notation. If someone decides to re-define integer addition, then the compiler should issue a warning ("Built-in operator being redefined."), but then let things proceed. If turning off all implicit conversion is required when this feature is used, so be it: Caveat Emptor! I, for one, would IMMEDIATELY use this feature to implement the "smart integer" features (similar to having NAN in D's floats) I was seeking in a long ago thread. This notation should also be "template safe", for quite a large set of ways to define templates. Should we discuss templates next?
 4) I don't see a point to smart pointers and such in a garbage collected
 language. Overloadable operators should be restricted to arithmetic
 operators.

No, why not let it all hang out? Let the compiler spew warning ad nauseum. But don't deny us the power to royally screw things up!
 5) Operator overloading should only be used to provide arithmetic operations
 on user defined arithmetic types. None of that << and >> for iostreams. I
 know many people like that, but a shift is not a stream operation. It just
 isn't.

My prior comment applies!
 6) I see no way to have the compiler enforce (5). Anyone caught violating
 (5) should be forced to carry the Stone of Shame.

No, they should be forced to endure "The Constant Stream Of Compiler Whining And Complaining". Sort of like what "gcc -Wall" does to my code... ;^)
 7) Note (3) means no virtual operator functions. To do that, you'd need:
     static int operator+(Foo x, int y)
     {
         return x.myadd(y);
     }
 so no great loss.

I think my proposed
 8) If there are to be conversion operators, they will not participate in
 implicit conversions, only explicit ones.

Agreed! The price for such power should be to force the user to be extremely explicit about what they are doing. Once you overload a predefined operator, the compiler should do no additional favors for you. Other than complain, of course!
 None of this is implemented or specified yet, it's just some thoughts.

And very good ones. I do NOT believe any such features of D need to be "efficient" or "optimizable". If they are, that would be great. All I ask is that they be "possible". -BobC
Feb 12 2002
prev sibling parent reply "D" <s_nudds hotmail.com> writes:
Operatoror overloading is an error gnashing at the bit to happen.  There is
<NO> valid justification for providing it.  There are arguments, but they
are ALL invalid, because code reliability must trump programming
convenience.

The problem with operator overloading is that it can be highly confusing.
What Isn't highly confusing however, and what does provide the same benefit
is providing the ability to create your own operators.

Existing operators have limited usefulness, even for simple vector
operations where there are two types of product.  What existing two
operators are you going to redefine for them?

Operator Overloading is very, very bad news.
OddesE <OddesE_XYZ hotmail.com> wrote in message
news:a2k8u8$fao$1 digitaldaemon.com...
 Ok, so one more time about operator overloading...  :)

 I read all the posts about operator overloading but I'm
 still a bit unsure about it...Do I want it, or don't I...

 I like about operator overloading the fact that you
 can add, subtract, compare or assign objects to
 one another much the same way as you can with
 normal primitive types.

 I hate some uses of operator overloading which
 seem really confusing to me. I always disliked
 the way cout and cin work.

Feb 04 2002
next sibling parent reply "Sean L. Palmer" <spalmer iname.com> writes:
Your first paragraph shows you to be closed minded.  By that argument,
pointers must be removed from the language, as well as anything that can be
remotely dangerous such as typecasting.  By the time you're done you won't
have much of a language left.

I bet you have problems figuring out what happens when you add a char to a
float and then add the result to an int.  The behavior of the operator is
governed by the types operated upon and the type conversion rules of the
language.  It gets a little more complex with operator overloading on user
types, but not to the point of unusability.

I'm not in favor of stripping away language utility to make up for the
deficiencies of the lowest common denominator programmer.  Your entire
argument is founded on that.  At least people can be trained proper coding
technique.  But it's difficult to add functionality to your compiler in most
cases (GCC at least allows it, but still not easy).  So removing
functionality is just going to cause language holes to exist that will give
people great big excuses to use a language that has all the functionality
they need, even if that language is C++ and allows you to shoot yourself in
the foot.

The main problem with operator overloading is that people don't bother to
look up the declaration of the variables they're dealing with.  For this I
blame hacks like Hungarian notation.  I'm sure it's something that a strong
IDE with one-button or tooltip browse info could solve nicely.

In any case, I expect people on my team to verify that their code works
before checking it in.  If you get operator overloading wrong, you'll notice
as soon as you run it because the behavior won't be what you expected.  (try
to assign the result of a dot product to a vector, or the result of a cross
product to a float, and you'll get a type mismatch of some kind at compile
time)

Sean


"D" <s_nudds hotmail.com> wrote in message
news:a3liu5$ruq$1 digitaldaemon.com...
 Operatoror overloading is an error gnashing at the bit to happen.  There i

 <NO> valid justification for providing it.  There are arguments, but they
 are ALL invalid, because code reliability must trump programming
 convenience.

 The problem with operator overloading is that it can be highly confusing.
 What Isn't highly confusing however, and what does provide the same

 is providing the ability to create your own operators.

 Existing operators have limited usefulness, even for simple vector
 operations where there are two types of product.  What existing two
 operators are you going to redefine for them?

Feb 04 2002
parent reply "D" <s_nudds hotmail.com> writes:
Sean L. Palmer writes:
 Your first paragraph shows you to be closed minded.  By that argument,
 pointers must be removed from the language, as well as anything that can

 remotely dangerous such as typecasting.  By the time you're done you won't
 have much of a language left.

Pointers have their place because they improve efficiency. Operator overloading provides no such advantage. It is simply a convenience feature for a minute number of situations that in most situations is abused thereby reducing code quality and maintainance. Defining new operators however is a different story. New operators can provide the same utility as existing ones without the associated problems of precidence and predefined meaning that limits the usefulness of the C/C++ implemntation. Members of the C religion like to argue that their God is the only God. When they accuse me of having a closed mind, I laugh. Sean L. Palmer writes:
 I bet you have problems figuring out what happens when you add a char to a
 float and then add the result to an int.

I do, because in crap languages like C/C++ the sign of char is not defined in the standard, the Char may be signed or unsigned and which is left up to the compiler. What is also wrong with C/C++ is that char is considered numeric at all. That is the height of stupidity. Rather characters should be relegated to characters, an only available as numbers if they are explicity cast as such. Members of the C faith will whine. Let them whine. Sean L. Palmer writes:
 I'm not in favor of stripping away language utility to make up for the
 deficiencies of the lowest common denominator programmer.

Clearly you do favour such a thing, since if you did not then youi would be programmig in assembler where you can create what you wish, when you wish. With assembler you have absolute freedom. So by selecting any HLL or MLL you have already decided to make a tradeoff. Your whine therefore has no significance, other than to show a reluctance to accept reason. Sean L. Palmer writes:
  At least people can be trained proper coding
 technique.  But it's difficult to add functionality to your compiler in

 cases (GCC at least allows it, but still not easy).  So removing
 functionality is just going to cause language holes to exist that will

 people great big excuses to use a language that has all the functionality
 they need, even if that language is C++ and allows you to shoot yourself

 the foot.

No. Language holes exist as a result of features that can not be completely implemented due to compiler constraints, or compile time requirements. Just as not every mathematical function has an easily computable inverse, not every design characteristic of a language can be fully implemented in concept across the language. Those areas where the implementation becomes difficult are the areas where there are holes in the language. One of the holes in the C language is the foolish method chosen to implement autoincrement, and the restrictions placed on the use of the operation in complex equations. Rather than have the compiler spend the time to properly implement the function, the morons who invented the C language (may they eternally burn in hell), decided to place the onus on the programmer to use the feature "properly". I.E. to use the feature in a manner in which the compiler doesn't fail. Sean L. Palmer writes:
 The main problem with operator overloading is that people don't bother to
 look up the declaration of the variables they're dealing with.

Wrong. The main problem with operator overloading is that the given meanings of the exiting operators do not lend themselves to the operations that typically need to be performed. This results in programmers doing things like using the division operator to compare strings, and stupid things like that. Sean L. Palmer writes:
 In any case, I expect people on my team to verify that their code works
 before checking it in.  If you get operator overloading wrong, you'll

 as soon as you run it because the behavior won't be what you expected.

 to assign the result of a dot product to a vector, or the result of a

 product to a float, and you'll get a type mismatch of some kind at compile
 time)

There are two kinds of product for vectors. Which of the two existing operators are you going to use to specify them?
Feb 04 2002
parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"D" <s_nudds hotmail.com> wrote in message
news:a3nl7n$2ao0$1 digitaldaemon.com...
 Sean L. Palmer writes:
 Your first paragraph shows you to be closed minded.  By that argument,
 pointers must be removed from the language, as well as anything that can

 remotely dangerous such as typecasting.  By the time you're done you


 have much of a language left.

Pointers have their place because they improve efficiency. Operator overloading provides no such advantage. It is simply a convenience

 for a minute number of situations that in most situations is abused

 reducing code quality and maintainance.

   Defining new operators however is a different story.  New operators can
 provide the same utility as existing ones without the associated problems

 precidence and predefined meaning that limits the usefulness of the C/C++
 implemntation.

   Members of the C religion like to argue that their God is the only God.
 When they accuse me of having a closed mind, I laugh.


 Sean L. Palmer writes:
 I bet you have problems figuring out what happens when you add a char to


 float and then add the result to an int.

I do, because in crap languages like C/C++ the sign of char is not defined in the standard, the Char may be signed or unsigned and which is left up

 the compiler.

 What is also wrong with C/C++ is that char is considered numeric at all.
 That is the height of stupidity.  Rather characters should be relegated to
 characters, an only available as numbers if they are explicity cast as

 Members of the C faith will whine.  Let them whine.


 Sean L. Palmer writes:
 I'm not in favor of stripping away language utility to make up for the
 deficiencies of the lowest common denominator programmer.

Clearly you do favour such a thing, since if you did not then youi would

 programmig in assembler where you can create what you wish, when you wish.
 With assembler you have absolute freedom.

 So by selecting any HLL or MLL you have already decided to make a

 Your whine therefore has no significance, other than to show a reluctance

 accept reason.


 Sean L. Palmer writes:
  At least people can be trained proper coding
 technique.  But it's difficult to add functionality to your compiler in

 cases (GCC at least allows it, but still not easy).  So removing
 functionality is just going to cause language holes to exist that will

 people great big excuses to use a language that has all the


 they need, even if that language is C++ and allows you to shoot yourself

 the foot.

No. Language holes exist as a result of features that can not be

 implemented due to compiler constraints, or compile time requirements.

 Just as not every mathematical function has an easily computable inverse,
 not every design characteristic of a language can be fully implemented in
 concept across the language.  Those areas where the implementation becomes
 difficult are the areas where there are holes in the language.

 One of the holes in the C language is the foolish method chosen to

 autoincrement, and the restrictions placed on the use of the operation in
 complex  equations.  Rather than have the compiler spend the time to
 properly implement the function, the morons who invented the C language

 they eternally burn in hell), decided to place the onus on the programmer

 use the feature "properly".  I.E. to use the feature in a manner in which
 the compiler doesn't fail.

 Sean L. Palmer writes:
  > The main problem with operator overloading is that people don't bother

 look up the declaration of the variables they're dealing with.

Wrong. The main problem with operator overloading is that the given meanings of the exiting operators do not lend themselves to the operations that typically need to be performed. This results in programmers doing things like using the division operator to compare strings, and stupid things like that. Sean L. Palmer writes:
 In any case, I expect people on my team to verify that their code works
 before checking it in.  If you get operator overloading wrong, you'll

 as soon as you run it because the behavior won't be what you expected.

 to assign the result of a dot product to a vector, or the result of a

 product to a float, and you'll get a type mismatch of some kind at


 time)

There are two kinds of product for vectors. Which of the two existing operators are you going to use to specify them?

The one you use most. The other you use a named function for. Without operator overloading you will always have to use a named function to describe mathematical operations. -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Feb 05 2002
parent reply "D" <s_nudds hotmail.com> writes:
Re: What ops to use for operator overloading for cross and dot products.

OddesE <OddesE_XYZ hotmail.com> wrote in message
news:a3pf92$4ul$1 digitaldaemon.com...
 The one you use most. The other you use a named function for.
 Without operator overloading you will always have to use a
 named function to describe mathematical operations.

Translation.... Operator overloading as provided by C++ is inadequate for even simple vector operations, which was it's primary reason for existance. I rest my case. Operator overloading is essentially useless. Allowing the programmer to define their own operators on the other hand is a valuable addition to a language.
Feb 06 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"D" <s_nudds hotmail.com> wrote in message
news:a3qtmm$2694$1 digitaldaemon.com...

 I rest my case.  Operator overloading is essentially useless.

 Allowing the programmer to define their own operators on the other hand is

 valuable addition to a language.

You are the only one in the group who has such an opinion. All others either don't use operator overloading at all, or want to be able to overload standard operators. Seems like you're outnumbered here, and since we have representatives from many areas of IT here, I guess it's an answer to a logical question, "What do you prefer", apllied to the entire target audience of D. Your arguments are not conceiving - noone had changed his mind. I believe the discussion is closed here. I'm out, at least. Period.
Feb 06 2002
parent "D" <s_nudds hotmail.com> writes:
Paul, left to themselves members of the C religion would change nothing,
because they are sheep
who generally don't know any better.

There are a plethora of langauges that resemble C, and each have been
created to appeal to the
irrational and inferior dictates of the C religionists.

If the author of D wishes to make the same mistakes as all of the others,
and as a result have
his langauge relegated to the same disgarded heap, that is his choice.

I don't recommend following in the footsteps of abject failure.
Why do you?

Pavel Minayev <evilone omen.ru> wrote in message
news:a3r4l9$2993$1 digitaldaemon.com...
 You are the only one in the group who has such an opinion. All others
 either don't use operator overloading at all, or want to be able to
 overload standard operators. Seems like you're outnumbered here, and
 since we have representatives from many areas of IT here, I guess it's
 an answer to a logical question, "What do you prefer", apllied to the
 entire target audience of D. Your arguments are not conceiving - noone
 had changed his mind. I believe the discussion is closed here. I'm out,
 at least. Period.

Feb 07 2002
prev sibling next sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
D wrote:

 Operatoror overloading is an error gnashing at the bit to happen.  There is
 <NO> valid justification for providing it.  There are arguments, but they
 are ALL invalid, because code reliability must trump programming
 convenience.

(please excuse my slight flamishness coming...) In a well controlled, well designed situation, programming convenience OFTEN LEADS TO CODE RELIABILITY. When the code is easy to write and read, and most importantly WHEN IT DOES WHAT IT SEEMS LIKE IT DOES, the two are one and the same. This whole idea that operator overloading = code confusion is vaporous. What operator overloading is a convenient shortcut into a certain function syntax. You could argue that "function naming is a bug-prone feature" because a programmer can write a function named one thing that does another. IT IS THE RESPONSIBILITY OF THE CODE REVIEWERS, IN CONSULTATION WITH THE ORIGINAL PROGRAMMER, TO ENSURE GOOD CODE DESIGN. Don't leave out an incredibly useful feature just because some people misuse it. If it's hard to implement in the compiler, I can understand that - we want a small, reliable compiler. But if it's easy to implement and we're not doing it out of some desire to "protect the user from himself"...well, I didn't become a programmer because I was content with what was "safe and easy." -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Feb 04 2002
parent reply "D" <s_nudds hotmail.com> writes:
Russ Lewis writes:
 In a well controlled, well designed situation, programming convenience

 LEADS TO CODE RELIABILITY.  When the code is easy to write and
 read, and most
 importantly WHEN IT DOES WHAT IT SEEMS LIKE IT DOES, the two
 are one and the same.

I agree. But well controlled, well designed situations <rarely> occur. So operator overloading <rarely> improves code reliability and clarity. Operator overloading is inferior in every respect to the ability to provide new operators. Providing new operators provides all of the benefits, and allows the programmer to avoid all of the pitfalls. I wouild make one exception. Equality. Equality can at all times be taken to be byte by byte identical. for comparison, and byte by byte assignment for assignment.
Feb 04 2002
parent reply "Serge K" <skarebo programmer.net> writes:
 I wouild make one exception. Equality.  Equality can at all times be taken
 to be byte by byte identical. for comparison, and byte by byte assignment
 for assignment.

According to IEEE 754, -0.0 == +0.0, but have different binary representation.
Feb 05 2002
next sibling parent Russell Borogove <kaleja estarcion.com> writes:
Serge K wrote:

I wouild make one exception. Equality.  Equality can at all times be taken
to be byte by byte identical. for comparison, and byte by byte assignment
for assignment.

According to IEEE 754, -0.0 == +0.0, but have different binary representation.

Just an anecdote, but I've run into a compiler that evaluated (-0.0 == +0.0) as false. I discovered this while porting code from a compiler that evaluated it as true. Let me tell you, that was a fun one, especially since the the only manifestation was "some of the rotating objects in the world rotate around the wrong axis." -Russell B
Feb 05 2002
prev sibling next sibling parent reply "Roberto Mariottini" <rmariottini lycosmail.com> writes:
"Serge K" <skarebo programmer.net> ha scritto nel messaggio
news:a3ql6l$21ts$1 digitaldaemon.com...
 I wouild make one exception. Equality.  Equality can at all times be


 to be byte by byte identical. for comparison, and byte by byte


 for assignment.

According to IEEE 754, -0.0 == +0.0, but have different binary representation.

Ant it's not the only example. CaseInsensitiveString s = "CIAO", t = "ciao"; if (s == t) ...
Feb 06 2002
parent reply "D" <s_nudds hotmail.com> writes:
What the hell is a case insensitive string.  Now that is a dum idea.  Case
insensitive comparison.  That is a smart idea.

In any case, If there was such a thing as a case insensitive string, then
make an exception.

I fail to see the difficulty.

By the way Roberto. if a case insensitive string is printed, is it printed
in upper or lower case?

Also Robert, you can create a case insensitive string simply by changing the
case to all upper or all lower during the load.  Since the case is
insensitive, altering the case during the load is not relevant is it?


Roberto Mariottini <rmariottini lycosmail.com> wrote in message
news:a3qtn7$2697$1 digitaldaemon.com...
 "Serge K" <skarebo programmer.net> ha scritto nel messaggio
 news:a3ql6l$21ts$1 digitaldaemon.com...
 I wouild make one exception. Equality.  Equality can at all times be


 to be byte by byte identical. for comparison, and byte by byte


 for assignment.

According to IEEE 754, -0.0 == +0.0, but have different binary representation.

Ant it's not the only example. CaseInsensitiveString s = "CIAO", t = "ciao"; if (s == t) ...

Feb 07 2002
next sibling parent reply "Roberto Mariottini" <rmariottini lycosmail.com> writes:
"D" <s_nudds hotmail.com> ha scritto nel messaggio
news:a3tvf5$r6f$1 digitaldaemon.com...
 What the hell is a case insensitive string.  Now that is a dum idea.  Case
 insensitive comparison.  That is a smart idea.

I think they are all good ideas.
 In any case, If there was such a thing as a case insensitive string, then
 make an exception.
 I fail to see the difficulty.

An exception is OK, if it's an exception. If it becomes a rule (i.e. there are other examples than CIString) then we must handle it somehow.
 By the way Roberto. if a case insensitive string is printed, is it printed
 in upper or lower case?

 Also Robert, you can create a case insensitive string simply by changing

 case to all upper or all lower during the load.  Since the case is
 insensitive, altering the case during the load is not relevant is it?

I'm thinking of Windows file names: they are case insensitive, but they preserve case. So, if an user wants to open "myfile.txt", but the system find "MyFile.txt", the open should be successful. On the other hand, when the file is opened, it is shown as "MyFile.txt" as it actually is. Ciao
Feb 07 2002
parent "D" <s_nudds hotmail.com> writes:
 "D" <s_nudds hotmail.com> ha scritto nel messaggio
 news:a3tvf5$r6f$1 digitaldaemon.com...
 What the hell is a case insensitive string.  Now that is a dum idea.


 insensitive comparison.  That is a smart idea.


Roberto Mariottini writes:
 I think they are all good ideas.

Clearly not. Case insensitive strings provide no advantage.
 By the way Roberto. if a case insensitive string is printed, is it


 in upper or lower case?

 Also Robert, you can create a case insensitive string simply by changing

 case to all upper or all lower during the load.  Since the case is
 insensitive, altering the case during the load is not relevant is it?


Roberto Mariottini writes:
 I'm thinking of Windows file names: they are case insensitive, but they
 preserve case.

I am well aware of case insensitity. Case sensitivity is one of the major failings of C and Unix in general. WORDS DO NOT CHANGE THEIR MEANING IF THEIR CASE CHANGES. Hence labels should not change their meaning either. D should be case insensitive. Case insensitivity is best performed through a case insensitive compare function, or through conveting the source and target strings to a common case before a typical case sensitive conversion. Now before someone blathers that such conversions are ineffiicent, the truth of the matter is that there is no difference in computational efficiency since with a case insensitive string, ultimately both the source and destination will need to be converted to a common case internally on a character by character basis during the comparison. Case insensitive strings would also require the inclusion of an additional string functions in the default library for every string operation where case differences must be ignored, thus increasing the minimal footprint for the resulting programs. The only advantage a native case insensitive string type has over a normal string type is that a case insensitive string will carry with it a flag that indicates that it is case insensitive. I admit that carrying such a flag is convenient. However, as long as we are carrying a single flag along with the string, there is no additional cost to us for carrying a generalized flag variable along with the string. A single byte can contain 8 or 16, general purpose flags, or be used for other identification purposes. One could use the register as an integer for the storage of an offset into the string, or an object reference, or anything else the programmer desires. So, it is clear that if case insensitivity is seen as important, a general purpose integer typed tag be associated with each string instead.
Feb 09 2002
prev sibling parent reply "Juan Carlos Arevalo Baeza" <jcab roningames.com> writes:
"D" <s_nudds hotmail.com> wrote in message
news:a3tvf5$r6f$1 digitaldaemon.com...

 What the hell is a case insensitive string.  Now that is a dum idea.

That'll be in your opinion, sir! Man, you've got to learn to control your wording, or else we're going to have a problem.
 Case insensitive comparison.  That is a smart idea.

I use case insensitive strings every day. They are not dumb. A case insensitice string is one that compares with disregard to case. So that, if "istring" is a case insensitive string, istring s1 = "D is better than C"; istring s2 = "D IS BETTER THAN C"; s1 == s2; // this is true. I agree that case-insensitivity is normally related to the comparisons themselves, not to the strings. But sometimes, it is a property of the strings. I use them in Win32 especially because I have a special string class that holds path names (call it pathname). And in Win32, path names are always case-insensitive. I see that as a property of the path as a whole, not of the comparisons applied to it. Makes for cleaner code in the end, because I don't need to remember that paths need different comparison functions.
 In any case, If there was such a thing as a case insensitive string, then
 make an exception.

 I fail to see the difficulty.

The difficulty is that, if every time it makes sense to make an exception you need to modify the language, the language gets bloated. It's best to be able to define extensions externally. In my opinion! ;-)
 By the way Roberto. if a case insensitive string is printed, is it printed
 in upper or lower case?

 Also Robert, you can create a case insensitive string simply by changing

 case to all upper or all lower during the load.  Since the case is
 insensitive, altering the case during the load is not relevant is it?

:) That's the dark side of case insensitive strings. Personally, I use the Windows file system way: case is stored as given, but comparisons don't use it. It's the same as ignoring part of a structure in its comparison operators. It does make for some awkward situations, I'll grant you that. Salutaciones, JCAB
Feb 08 2002
parent "D" <s_nudds hotmail.com> writes:
As I recognized, case insensitivity is indeed a good thing.  A native type
case
insensensitive string is not.

As you indicate in those instances where they are convenient, they can be
created
by defining a new type.

Good programming languages do not have holes.  Questions do not arrise as to
how a specific
situation will be handled.

Good programming languages follow a design philosophy which indicate the
path taken when
or more logical options are available.  That is language consistancy.

Case invariant strings raise too many questions as to how specific instances
will be handled.  They
increase the minimum footprint of the language.  To be implemented properly
an insensitivity flag
must be stored along with the string, and if that is to be the case, on a
cost/benefit basis it is better
to break out the insensitivity flag to a general purpose flags register or
integer so that it can be used
for other purposes.


Juan Carlos Arevalo Baeza <jcab roningames.com> wrote in message
news:a419m3$2kgj$1 digitaldaemon.com...
    :) That's the dark side of case insensitive strings. Personally, I use
 the Windows file system way: case is stored as given, but comparisons

 use it. It's the same as ignoring part of a structure in its comparison
 operators. It does make for some awkward situations, I'll grant you that.

Feb 09 2002
prev sibling parent reply "D" <s_nudds hotmail.com> writes:
Really?  I didn't know that.

Don't follow IEEE 754 specifiations as it is an ill conceived and irrational
standard.

If the language is to have ouitput structures, I would seem appropariate
that in the assignment phase from a standard struct that the conversion
of -0 to +0 be made.

Serge K <skarebo programmer.net> wrote in message
news:a3ql6l$21ts$1 digitaldaemon.com...
 I wouild make one exception. Equality.  Equality can at all times be


 to be byte by byte identical. for comparison, and byte by byte


 for assignment.

According to IEEE 754, -0.0 == +0.0, but have different binary representation.

Feb 06 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"D" <s_nudds hotmail.com> wrote in message
news:a3qts2$26e1$1 digitaldaemon.com...
 Really?  I didn't know that.

 Don't follow IEEE 754 specifiations as it is an ill conceived and

 standard.

Yeah, and then you can throw your FPU away and forget about it...
Feb 06 2002
parent "D" <s_nudds hotmail.com> writes:
Why is that Paul.  Are you unable to change -0.0 into 0.0?

I thought you were a programmer.
Am I mistaken?

Pavel Minayev <evilone omen.ru> wrote in message
news:a3r4g9$298b$2 digitaldaemon.com...
 "D" <s_nudds hotmail.com> wrote in message
 news:a3qts2$26e1$1 digitaldaemon.com...
 Really?  I didn't know that.

 Don't follow IEEE 754 specifiations as it is an ill conceived and

 standard.

Yeah, and then you can throw your FPU away and forget about it...

Feb 07 2002
prev sibling parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"D" <s_nudds hotmail.com> wrote in message
news:a3liu5$ruq$1 digitaldaemon.com...
 Operatoror overloading is an error gnashing at the bit to happen.  There

 <NO> valid justification for providing it.  There are arguments, but they
 are ALL invalid, because code reliability must trump programming
 convenience.

I wouldn't say that code reliability is that much at stake with operator overloading. Consider the next piece of code: MyClass result.Assign(MyClass::.Add (Var1, MyClass::Multiply (Var1, Var3))); Then consider the same code using operator overloading: MyClass result = Var1 + Var1 * Var3; Now I doubt that there will be many people telling me the first snippet is more readable than the second. After I wrote it, I had to examine it 4 times to make sure I had it correct, with all the braces and the order of the arguments. I am not talking about how *writable* the code is, mind you, that does not seem very important to me. Everyone will testify that the second part is more easy to write, with less characters and less parenthesis, but I don't care about that. I almost never use acronyms like w8 4 me, RTFM, IMHO, WYSISYG etcetera, because, even though they are easier to write, they are more difficult to read. But when code is easier to *read* as well as write, I think that leads to more reliable code!
 The problem with operator overloading is that it can be highly confusing.
 What Isn't highly confusing however, and what does provide the same

 is providing the ability to create your own operators.

Mmmm.... So you don't understand what A + B or C * D means, but you do understand all of the very complex operators that exist in math today, as well as the ones that I personally come up with? This just doesn't make sense to me...
 Existing operators have limited usefulness, even for simple vector
 operations where there are two types of product.  What existing two
 operators are you going to redefine for them?

This example is mentioned often, and it is indeed a very good one. Matrix math is a very important part of programming and indeed there should be a standard for such things. This doesn't put an end to the discussion though...Are there many different ways to interpret A = B, or if (A == B)? These are the operators used and overloaded most often, and they are valid operations for almost any class you can come up with. What is more readable to you: if (! A.Cmp (B)) or if (A == B) I especially love the fact that there is a ! operator in the first expression, that to me is quitte counter-intuitive, and that the ==, !=, < and > operators are mixed together, even though some classes support testing for equality, but not for sortability. When A.Cmp(B) returns -1, does that mean A is smaller than B, or that it is just not equal to it? You gotta love that ambiguity! If a simple test for equality isn't unambiguis and is counter intuitive, that tells a long story.
 Operator Overloading is very, very bad news.

There are some very bad things that *can* be done with operator overloading, but there are also some very good. What my proposal (which you said nothing about) tries to do, is use the best things of both worlds. It eliminates a lot of the mistakes that can be made using operator overloading, such as overloading == but not !=, it allows for both forms of coding to be used (and even exchanged using DML) and it could create more readable code. Walter, *please* create some basic interfaces like IAssignable, IComparable and ISortable! It would make D code from different users look and behave the same. We could test if a class supports ISortable and there would be much less different ways of doing the same thing. Also, please ditch Cmp(). Testing for equality and sortability are different things that shouldn't be mixed like C does. Even if you don't want to make a decision about operator overloading just yet, interfaces like this would leave the door open while gaining important benefits right away! If you never add operator overloading to the language we at least all use the same ways of assigning one object to another, or comparing them or testing which one is larger than the other etc. I would hate to see some people define assignment functions as Assign(), others as Copy() and again others as Clone(). -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Feb 04 2002
parent reply "D" <s_nudds hotmail.com> writes:
OddesE <OddesE_XYZ hotmail.com> wrote in message
 I wouldn't say that code reliability is that much at stake
 with operator overloading. Consider the next piece of code:

 MyClass result.Assign(MyClass::.Add (Var1, MyClass::Multiply (Var1,

 Then consider the same code using operator overloading:

 MyClass result = Var1 + Var1 * Var3;

Consider this piece of code define op var1 .* var3 = MyClass::Multiply(Var1,Var3) define op var1. .+ var3 = MyClass::Add(Var1.Var3) MyClass::result = Var1 .+ Var1 .* Var3 I fail to see your complaint Mr OdessE. Perhaps you can explain it to me. OdessE writes:
 Now I doubt that there will be many people telling me the
 first snippet is more readable than the second.

Now I dount that there will be many people telling me that MyClass::result = Var1 .+ Var1 .* Var3 is any less readable than MyClass result = Var1 + Var1 * Var3; OdessE writes:
 After I wrote
 it, I had to examine it 4 times to make sure I had it correct,
 with all the braces and the order of the arguments.

I had no such burden.
 The problem with operator overloading is that it can be highly


 What Isn't highly confusing however, and what does provide the same

 is providing the ability to create your own operators.


OdessE writes:
 Mmmm.... So you don't understand what A + B or C * D
 means, but you do understand all of the very complex
 operators that exist in math today, as well as the ones that
 I personally come up with?

Clearly no one can, since the meaning of + and * are dependent on the types of A, B, C and D. You may claim to know the meaning, but if so, you are lying to yourself. OdessE writes:
 if (! A.Cmp (B))

 or

 if (A == B)

It depends on what A and B are.and what you are trying to do. Perhaps A and B are objects, the == syntax can have three equally appropriate meanigns. A is numerically identical to B, A is functionally identical to B, A and B are the same object. With one equal sign, how do you intend to distingish between these three poetntial meanings? How do you intend to implement more than one of them at a time? I await your response.
 Operator Overloading is very, very bad news.


OdessE writes:
 There are some very bad things that *can* be done with
 operator overloading, but there are also some very good.

The bad outweighs to good. <period>
Feb 04 2002
next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"D" <s_nudds hotmail.com> wrote in message
news:a3nmm4$2b86$1 digitaldaemon.com...

 Now I dount that there will be many people telling me that

 MyClass::result =  Var1 .+ Var1 .* Var3

 is any less readable than

 MyClass result = Var1 + Var1 * Var3;

I do. If I use your library, I'd expect + to add vectors. I would have never think of .+, before reading the docs to the point where it's mentioned.
Feb 04 2002
parent reply "D" <s_nudds hotmail.com> writes:
 "D" <s_nudds hotmail.com> wrote in message

 Now I dount that there will be many people telling me that

 MyClass::result =  Var1 .+ Var1 .* Var3

 is any less readable than

 MyClass result = Var1 + Var1 * Var3;


Pavel Minayev <evilone omen.ru> wrote in message news:a3o1gc$2fji$1 digitaldaemon.com...
 I do. If I use your library, I'd expect + to add vectors.
 I would have never think of .+, before reading the docs to the
 point where it's mentioned.

Yet you see .+ being applied to a variable, perhaps a vector, perhaps not. This visual cue tells you that you had better pay careful attention to that statement because it is using user defined operators and probably aggregate variables. With MyClass result = Var1 + Var1 * Var3; on the other hand there are no visual cues and the expression could very well be a simple one that does not need further investigation. Visual cues are a good thing. They aid us in avoiding error.
Feb 05 2002
parent reply "Roberto Mariottini" <rmariottini lycosmail.com> writes:
"D" <s_nudds hotmail.com> ha scritto nel messaggio
news:a3o85r$2jck$1 digitaldaemon.com...
 Yet you see .+ being applied to a variable, perhaps a vector, perhaps not.

 This visual cue tells you that you had better pay careful attention to

 statement because it is using user defined operators and probably

 variables.

 With

 MyClass result = Var1 + Var1 * Var3;

 on the other hand there are no visual cues and the expression could very
 well be a simple one that does not need further investigation.

 Visual cues are a good thing.  They aid us in avoiding error.

I must admit you have a point here, but that little dot can be easily hidden inside a big expression. Any other idea? I think it's useful to know if I'm calling an overloaded operator or not, but adding the littlest dot definitely isn't the solution. Ciao
Feb 05 2002
parent "D" <s_nudds hotmail.com> writes:
Roberto Mariottini <rmariottini lycosmail.com> wrote in message
news:a3okd3$2oil$1 digitaldaemon.com...

 I must admit you have a point here, but that little dot can be easily

 inside a big expression. Any other idea?
 I think it's useful to know if I'm calling an overloaded operator or not,
 but adding the littlest dot definitely isn't the solution.

I toyed with the idea of bracketing them <+> <-> etc..
Feb 05 2002
prev sibling parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"D" <s_nudds hotmail.com> wrote in message
news:a3nmm4$2b86$1 digitaldaemon.com...
 OddesE <OddesE_XYZ hotmail.com> wrote in message
 I wouldn't say that code reliability is that much at stake
 with operator overloading. Consider the next piece of code:

 MyClass result.Assign(MyClass::.Add (Var1, MyClass::Multiply (Var1,

 Then consider the same code using operator overloading:

 MyClass result = Var1 + Var1 * Var3;

Consider this piece of code define op var1 .* var3 = MyClass::Multiply(Var1,Var3) define op var1. .+ var3 = MyClass::Add(Var1.Var3) MyClass::result = Var1 .+ Var1 .* Var3 I fail to see your complaint Mr OdessE. Perhaps you can explain it to me.

Consider this pieces of code: define op var1 ** var3 = MyClass::Multiply(Var1,Var3) define op var1. *+ var3 = MyClass::Add(Var1.Var3) define op var1 #* var3 = MyClass::Multiply(Var1,Var3) define op var1. #+ var3 = MyClass::Add(Var1.Var3) define op var1 $* var3 = MyClass::Multiply(Var1,Var3) define op var1. $+ var3 = MyClass::Add(Var1.Var3) define op var1 * var3 = MyClass::Multiply(Var1,Var3) define op var1. + var3 = MyClass::Add(Var1.Var3) define op var1 &* var3 = MyClass::Multiply(Var1,Var3) define op var1. &+ var3 = MyClass::Add(Var1.Var3) MyClass::result = Var1 *+ Var1 ** Var3 MyClass::result = Var1 #+ Var1 #* Var3 MyClass::result = Var1 $+ Var1 $* Var3 MyClass::result = Var1 + Var1 * Var3 MyClass::result = Var1 &+ Var1 &* Var3 Now you tell me that you don't see any problems in this? How am I supposed to know what strange character sequence a programmer selected to convey a plus operation? You could use some kind of standard, but what is the point? Why do you think people can easily abuse normal operator overloading, but replacing the normal operator sign that everyone knows with some weird sign nobody knows wil leviate this problem? Who keeps me from doing this: define op var1 .* var3 = MyClass::Add (Var1,Var3) define op var1. .+ var3 = MyClass::Multiply (Var1.Var3) MyClass::result = Var1 .+ Var1 .* Var3 Now do you still understand this example? I really don't see any big differences in this. Your solution does not prevent the abuse you keep talking about. Ok, so maybe if people see .= they will look it up in the docs. Or maybe they just assume it is assign. At least with the normal = there is a defined meaning what the operator *should* do. Now it could be anything. I think the code just got much _less_ self-documenting!
 OdessE writes:
 Now I doubt that there will be many people telling me the
 first snippet is more readable than the second.

Now I dount that there will be many people telling me that MyClass::result = Var1 .+ Var1 .* Var3 is any less readable than MyClass result = Var1 + Var1 * Var3;

I am telling it. I never saw an operator .+ before. Not in Delphi/Java/C/C++, nor in math. How am I supposed to know what it means? I could *assume* it means plus, but I wouldn't know it. At least with normal + I know what it normally means (in math or other languages).
 OdessE writes:
 After I wrote
 it, I had to examine it 4 times to make sure I had it correct,
 with all the braces and the order of the arguments.

I had no such burden.

Good for you, but you are contradicting yourself with this cowboy-coder comment. So if you know what it means than it is not a problem eh? You still didn't say that MyClass result.Assign(MyClass::.Add (Var1, MyClass::Multiply (Var1, Var3))); is more readable than MyClass result = Var1 + Var1 * Var3; probably because it just isn't.
 The problem with operator overloading is that it can be highly


 What Isn't highly confusing however, and what does provide the same

 is providing the ability to create your own operators.


OdessE writes:
 Mmmm.... So you don't understand what A + B or C * D
 means, but you do understand all of the very complex
 operators that exist in math today, as well as the ones that
 I personally come up with?

Clearly no one can, since the meaning of + and * are dependent on the

 of A, B, C and D.

And clearly no one can now the meaning of .+ and .* At least with normal operators I know what they usually do and have a reference in math or other languages to draw experience on.
 You may claim to know the meaning, but if so,  you are lying to yourself.

If I write a function CString MyClass::ToString(), are you going to trust me that it will convert MyClass to a string? If you don't, good luck spending the rest of your life trying to read in the (sometimes nonexistent) documentation of code trying to figure out what bloody obvious functions do. If you do, how can you be sure I didn't write the function in such a way that it formats your hard-drive? The fact is you can't. I could even have written misleading documentation that tells you that my function converts MyClass to a CString, when in fact it just wipes your disc. Are you really saying you are manually checking the code of every third party function you ever use? Functions should have descriptive names and they should do what you expect of them. If they don't, the code is effectively broken. Everyone knows what string1 = string2 + string3 is supposed to do. If you don't you can always still look it up. At least with normal operators there is a common base of experience people can draw from.
 OdessE writes:
 if (! A.Cmp (B))

 or

 if (A == B)

It depends on what A and B are.and what you are trying to do. Perhaps A

 B are objects, the == syntax can have three equally appropriate meanigns.

 is numerically identical to B,  A is functionally identical to B, A and B
 are the same object.

 With one equal sign, how do you intend to distingish between these three
 poetntial meanings?  How do you intend to implement more than one of them

 a time?

 I await your response.

I don't really see how Cmp solves these issues better then operator overloading. And if you compare two numbers to see if they are equal, do you try to find out if the are the same instance of an int? Draw from experience. int A = 10; int B = 10; int C = 0; if (A == B) C = A; B = 5; What value does C have?
 Operator Overloading is very, very bad news.


OdessE writes:
 There are some very bad things that *can* be done with
 operator overloading, but there are also some very good.

The bad outweighs to good. <period>

No it doesn't. Period. -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Feb 05 2002
parent reply "D" <s_nudds hotmail.com> writes:
OddesE <OddesE_XYZ hotmail.com> wrote in message
news:a3ph43$61j$1 digitaldaemon.com...
 Consider this pieces of code:

 define op var1 ** var3 = MyClass::Multiply(Var1,Var3)
 define op var1. *+ var3 = MyClass::Add(Var1.Var3)
 define op var1 #* var3 = MyClass::Multiply(Var1,Var3)
 define op var1. #+ var3 = MyClass::Add(Var1.Var3)
 define op var1 $* var3 = MyClass::Multiply(Var1,Var3)
 define op var1. $+ var3 = MyClass::Add(Var1.Var3)
 define op var1  * var3 = MyClass::Multiply(Var1,Var3)
 define op var1.  + var3 = MyClass::Add(Var1.Var3)
 define op var1 &* var3 = MyClass::Multiply(Var1,Var3)
 define op var1. &+ var3 = MyClass::Add(Var1.Var3)

 MyClass::result =  Var1 *+ Var1 ** Var3
 MyClass::result =  Var1 #+ Var1 #* Var3
 MyClass::result =  Var1 $+ Var1 $* Var3
 MyClass::result =  Var1  + Var1  * Var3
 MyClass::result =  Var1 &+ Var1 &* Var3

Yup I do see difficulty with your code. It's difficult to read because you have chosen to define the same function for multiply and add a total of 5 times. Very poor programming practice. Consider the equivalent defined only once.... define op var1 ** var3 = MyClass::Multiply(Var1,Var3) define op var1. *+ var3 = MyClass::Add(Var1.Var3) MyClass::result = Var1 *+ Var1 ** Var3 Reasonably readable but flawed. I find it odd that you would see the need to create a new operator by combining two thers. Still purposely trying to write obfuscated code I guess. Here is a superior alternative. define op var1 :* var3 = MyClass::Multiply(Var1,Var3) define op var1. :+ var3 = MyClass::Add(Var1.Var3) MyClass::result = Var1 :+ Var1 :* Var3 Yes, quite readable now that the purposeful obfuscation has been removed. Odesse writes:
 How am I supposed to know what strange character
 sequence a programmer selected to convey a plus operation?

One presumes that programmers will take care in selecting meaninful names for their operators just as they are preseumed to select meaninful names for their functions. Also, since operator overloading is abolished, there is a 1:1 mapping of operators to function (with the exception of equality). So all we need do is keep a our list of operators handy and we can understand any function presented to us. It's as simple as that. Odesse writes:
 You could use some kind of standard, but what is the
 point?

No standards are needed. :V+ is a nice enough name for vector add. If vector operators are the only things added the programmer might select :+ Matrix multiplication might could be indicated by :M* or :MtxMul, or whatever name the programmer sees fit to use. Odesse writes::
 Why do you think people can easily abuse normal
 operator overloading, but replacing the normal operator
 sign that everyone knows with some weird sign nobody
 knows wil leviate this problem?

Primarily because as you yoursef showed in another thread, they aer forced to by the limited number of existing operators. Odesse writes:
 Who keeps me from doing this:

 define op var1 .* var3 = MyClass::Add (Var1,Var3)
 define op var1. .+ var3 = MyClass::Multiply (Var1.Var3)

 MyClass::result =  Var1 .+ Var1 .* Var3

Absolutely nothing. Do you regularly program in that manner? Do you label your functions with names like "aelfkie" and "xxxxxxx"? Chosing appropriat labels is one aspect of proper programming. Odesse writes:
 I really don't see any big differences in this.
 Your solution does not prevent the abuse you keep talking
 about.

There are 4 differences. 1. Existing operators do not change their meaning and therefore all lines containing existing operators can be taken at face value rather than being suspect of hiding some unsuspected behaviour. 2. There is a 1:1 relationship between operator and function which enables the programmer to use a simple operator table to figure out what a specific equation means 3. I recommend that all new operators have the same precedence. Hence there is no confusion in the order of operations, and no unnatural consequences to what would otherwise be automatic reordering. 4. New operators would provide visual cues that readily distinguish them from existing operators, thereby allowing the programmer to readily identify new program behaviour. Odesse writes:
 Ok, so maybe if people see .= they will look it up
 in the docs. Or maybe they just assume it is assign. At least
 with the normal = there is a defined meaning what the
 operator *should* do. Now it could be anything. I think the
 code just got much _less_ self-documenting!

Now they could presume it is an assignment, but the colon at the front of the operator indicates new behaviour that distinguishes it from simple assignment. You may elect to ignore visual cues like that, but I would not. On the other hand with overloading you wouldn't see := (colon equal) you would see = (equal) Which is identical to = (equal) Yet the first equal under your regime of operator overloading would have a meaning that is entirely different than the second equal symbol,. Your system, no visual cues. Your system is inferior.
 OdessE writes:
 Now I doubt that there will be many people telling me the
 first snippet is more readable than the second.

Now I dount that there will be many people telling me that MyClass::result = Var1 .+ Var1 .* Var3 is any less readable than MyClass result = Var1 + Var1 * Var3;


Odesse writes:
 I am telling it. I never saw an operator .+ before. Not in
 Delphi/Java/C/C++, nor in math. How am I supposed to
 know what it means?

You go to the top of the module, find the definition and read it. Alternately you pull out your quick reference chart and read it. Alternately you rememher what it means and continue with the interpretation. I fail to see your difficulty. Odesse writes:
  I could *assume* it means plus,
 but I wouldn't know it. At least with normal + I know
 what it normally means (in math or other languages).

You can assume many things. The colon in front of the label is a visual cue that you may not assume anythign. Assume at your own peril.
 OdessE writes:
 After I wrote
 it, I had to examine it 4 times to make sure I had it correct,
 with all the braces and the order of the arguments.

I had no such burden.

Good for you, but you are contradicting yourself with this cowboy-coder comment. So if you know what it means than it is not a problem eh?

Nope, it's not a problem because you can easily remember what it means as well. Most importantly the colon at the front of the label is your cue that unusual behaviour is taking place. Odesse writes:
 You still didn't say that

 MyClass result.Assign(MyClass::.Add (Var1, MyClass::Multiply (Var1,

 is more readable than

 MyClass result = Var1 + Var1 * Var3;

 probably because it just isn't.

Yes, the first statement is more readable than the second because in the case of the second statement we are not told what + and * do. We only know that they perform some unknown operation, and that operation depends on the variable types which are not specified. Hence we can say nothing about the second function. However in the case of :+ and :* there is a 1:1 correspondance between function and operator label so knowing that :* = Myclass::Multiply(Var1,Var3) :+ = Myclass::Add(Var1,Var3) We know everything we need to know about the equation. It's really quite simple. I fail to see your objection.
 The problem with operator overloading is that it can be highly


 What Isn't highly confusing however, and what does provide the same

 is providing the ability to create your own operators.


OdessE writes:
 Mmmm.... So you don't understand what A + B or C * D
 means, but you do understand all of the very complex
 operators that exist in math today, as well as the ones that
 I personally come up with?

Clearly no one can, since the meaning of + and * are dependent on the

 of A, B, C and D.


Odesse writes:
 And clearly no one can now the meaning of .+ and .*

Since there is a 1:1 correspondance of label and funtion, you consult your opcode table. You can not do this with + and * since there are no visual clues that + and * are doing anything outside their ordinary meaning. a = b + c d = e + f In your inferior system of operator overloading the first example above may be doing a simple addition,. while the second could be adding a graphic to a web page an uploading the result to a server. Quite foolish. Odesse writes:
 At least with normal operators I know what they usually do and
 have a reference in math or other languages to draw experience on.

And you can still use that by creating new operators with names similar to the existing operators. :+ in place of + for example. But you have the advantage of creating new operators with more appropriate labels as well For example :dot or :cross for dot and cross products If the colon were more visible on this screen I would have used colon period, for dot product and colon x for cross product. So all of the advantages of operator overloading exist while all of the failures of C++ style operator overloading can be avoided. Operator overloading is clearly inferior. .
 It depends on what A and B are.and what you are trying to do.  Perhaps A

 B are objects, the == syntax can have three equally appropriate


 A
 is numerically identical to B,  A is functionally identical to B, A and


 are the same object.

 With one equal sign, how do you intend to distingish between these three
 poetntial meanings?  How do you intend to implement more than one of


 at
 a time?

 I await your response.


Odesse writes:
 I don't really see how Cmp solves these issues better then operator
 overloading.
 And if you compare two numbers to see if they are equal, do you try to

 out if the are the same instance of an int? Draw from experience.

That may very well be a requirement yes. That int may very well be a semiphore used for synchronization, or used by the program to tell if it is looking at an instance of itself. Once again I fail to see your complaint. Odesse writes:
 int A = 10;
 int B = 10;
 int C = 0;

 if (A == B)
    C = A;
 B = 5;

 What value does C have?

If this langauge allows all operators to be overloaded even for the base types then we do not know the answer because somewhere elsewhere in the program the operators may have hand their meaning altered. Odesse, your argument has been obliterated by common sense. At this point you are simply embarrasing yourself. I recommend you stop before damaging your reputation further.
Feb 06 2002
parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"D" <s_nudds hotmail.com> wrote in message
news:a3r33g$28jj$1 digitaldaemon.com...
 OddesE <OddesE_XYZ hotmail.com> wrote in message
 news:a3ph43$61j$1 digitaldaemon.com...
 Consider this pieces of code:

 define op var1 ** var3 = MyClass::Multiply(Var1,Var3)
 define op var1. *+ var3 = MyClass::Add(Var1.Var3)
 define op var1 #* var3 = MyClass::Multiply(Var1,Var3)
 define op var1. #+ var3 = MyClass::Add(Var1.Var3)
 define op var1 $* var3 = MyClass::Multiply(Var1,Var3)
 define op var1. $+ var3 = MyClass::Add(Var1.Var3)
 define op var1  * var3 = MyClass::Multiply(Var1,Var3)
 define op var1.  + var3 = MyClass::Add(Var1.Var3)
 define op var1 &* var3 = MyClass::Multiply(Var1,Var3)
 define op var1. &+ var3 = MyClass::Add(Var1.Var3)

 MyClass::result =  Var1 *+ Var1 ** Var3
 MyClass::result =  Var1 #+ Var1 #* Var3
 MyClass::result =  Var1 $+ Var1 $* Var3
 MyClass::result =  Var1  + Var1  * Var3
 MyClass::result =  Var1 &+ Var1 &* Var3

Yup I do see difficulty with your code. It's difficult to read because

 have
 chosen to define the same function for multiply and add a total of 5


I actually did not do that. 5 other programmers did that. Some of them were on other teams, others were with other companies that we use libraries of. All these declarations were in different files and were part of different libraries. Unfortunately they all do the same thing, they all add two strings. All these programmers noticed the lack of string support in language X but, since it did include adding new operators, they invented one of their own. Unfortunately I have to memorize them all, or find different libraries.
 Very poor programming practice.
 Consider the equivalent defined only once....
 define op var1 ** var3 = MyClass::Multiply(Var1,Var3)
 define op var1. *+ var3 = MyClass::Add(Var1.Var3)

You try to convince hundreds of programmers to use your style... Math already has defined these operators, but no, you can't use those...Invent some of your own...
 MyClass::result =  Var1 *+ Var1 ** Var3


 Reasonably readable but flawed.  I find it odd that you would see the need
 to create a new operator by combining
 two thers.  Still purposely trying to write obfuscated code I guess.

No I just had no clue, like all programmers according to you.
 Here is a superior alternative.

 define op var1 :* var3 = MyClass::Multiply(Var1,Var3)
 define op var1. :+ var3 = MyClass::Add(Var1.Var3)

 MyClass::result =  Var1 :+ Var1 :* Var3

 Yes, quite readable now that the purposeful obfuscation has been removed.

What does the : mean? Where is the standard? What prevents other companies from using entirely different standards? How am I supposed to remember all this? I am not as good as you at memorizing tables with useless data...
 Odesse writes:
 How am I supposed to know what strange character
 sequence a programmer selected to convey a plus operation?

One presumes that programmers will take care in selecting meaninful names for their operators just as they are preseumed to select meaninful names for their functions. Also, since operator overloading is abolished, there is a 1:1 mapping of operators to function (with the exception of equality). So all we need do is keep a our list of operators handy and we can understand any function presented to us. It's as simple as that.

Great, all these lists and tables. Let's name our variables var1, var2 and var3, then keep a list of what they mean.
 Odesse writes:
 You could use some kind of standard, but what is the
 point?

No standards are needed. :V+ is a nice enough name for vector add.

Your opinion. I don't agree. I still don't mean what the colon stands for. I could guess at the V, but I don't like guessing what code does, I like knowing so from experience and common sense.
 If vector operators are the only things added the programmer might select

Ditch the colon, of which I don't understand the meaning, and what is left?
 Matrix multiplication might could be indicated by :M* or :MtxMul, or
 whatever
 name the programmer sees fit to use.

Ah yes, :MtxMul... Starts to sound a lot like a regular function name doesn't it? What is the point?
 Odesse writes::
 Why do you think people can easily abuse normal
 operator overloading, but replacing the normal operator
 sign that everyone knows with some weird sign nobody
 knows wil leviate this problem?

Primarily because as you yoursef showed in another thread, they aer forced to by the limited number of existing operators.

Yes, but why replace the existing ones with substitutes that do exactly the same, such as :V+ ? Adding a sqrt operator is a different matter altogether, there doesn't exist one in the programming language at the moment.
 Odesse writes:
 Who keeps me from doing this:

 define op var1 .* var3 = MyClass::Add (Var1,Var3)
 define op var1. .+ var3 = MyClass::Multiply (Var1.Var3)

 MyClass::result =  Var1 .+ Var1 .* Var3

Absolutely nothing. Do you regularly program in that manner?

I don't, but you keep saying that programmers are clueless and do such things. I am asking you how your method prevents this.
 Do you label your functions with names like "aelfkie" and "xxxxxxx"?

 Chosing appropriat labels is one aspect of proper programming.


 Odesse writes:
 I really don't see any big differences in this.
 Your solution does not prevent the abuse you keep talking
 about.

There are 4 differences. 1. Existing operators do not change their meaning and therefore all lines containing existing operators can be taken at face value rather than being suspect of hiding some unsuspected behaviour.

With operator overloading (if used right) they don't change their meaning either. + means to add something. You are just changing the something you want to add. You could define operator+ to multiply it's parameters ofcourse, but you could do that using any of the constructs we are talking about.
 2. There is a 1:1 relationship between operator and function which enables
     the programmer to use a simple operator table to figure out what a
 specific
     equation means

I don't like those tables, and with normal operators you don't need them, you already know what + means.
 3. I recommend that all new operators have the same precedence. Hence

     is no confusion in the order of operations, and no unnatural
 consequences to
    what would otherwise be automatic reordering.

A yes: Assuming a class int64 with operators defined for adding and multiplication: int64 a, b, c; a := a :+ b :* c; Now you will get different results then you would expect from plus and multiply operations... It just doesn't make sense that all math knowledge becomes invalid when using operators.
 4. New operators would provide visual cues that readily distinguish them
 from
     existing operators, thereby allowing the programmer to readily

 new program
     behaviour.

The behaviour for + is not new, it is still adding two entities. You are just allowing new types to be added.
 Odesse writes:
 Ok, so maybe if people see .= they will look it up
 in the docs. Or maybe they just assume it is assign. At least
 with the normal = there is a defined meaning what the
 operator *should* do. Now it could be anything. I think the
 code just got much _less_ self-documenting!

Now they could presume it is an assignment, but the colon at the front of the operator indicates new behaviour that distinguishes it from simple assignment.

What new behaviour? What strange things are you doing tou your variable?
 You may elect to ignore visual cues like that, but I would not.

 On the other hand with overloading you wouldn't see

 :=   (colon equal)

 you would see

 =  (equal)

 Which is identical to

 =  (equal)

 Yet the first equal under your regime of operator overloading would have a
 meaning that is entirely
 different than the second equal symbol,.

Right, entirely different. No relation whatsoever. Are you kidding me? I am assigning one variable to another, since when does the assignment of objects of a class have nothing in commom with assigning integers or floats? Should we also use different operators for addition of all basic types? The have "nothing in common" after all...
 Your system, no visual cues.

 Your system is inferior.





 OdessE writes:
 Now I doubt that there will be many people telling me the
 first snippet is more readable than the second.

Now I dount that there will be many people telling me that MyClass::result = Var1 .+ Var1 .* Var3 is any less readable than MyClass result = Var1 + Var1 * Var3;


Odesse writes:
 I am telling it. I never saw an operator .+ before. Not in
 Delphi/Java/C/C++, nor in math. How am I supposed to
 know what it means?

You go to the top of the module, find the definition and read it. Alternately you pull out your quick reference chart and read it. Alternately you rememher what it means and continue with the

 I fail to see your difficulty.

Usability. The code should be as self-documenting as possible. I shouldn't need a quick reference chart, or at least as less as possible.
 Odesse writes:
  I could *assume* it means plus,
 but I wouldn't know it. At least with normal + I know
 what it normally means (in math or other languages).

You can assume many things. The colon in front of the label is a visual cue that you may not assume anythign. Assume at your own peril.

Do you never assume anything about other people's code? If someone makes a list class and gives it a Add function, I will assume it means adding something to the list. I am not going to assume it means removing elements. When you are programming with an API, say Win32, how do you find out what function to use? When you need to create a window, do you really read all the documentation for all API functions, or are you going to assume that CreateWindowEx will create a window, and then just check it's documentation to see what parameters you need? Assumptions are always made, either conciously or unconciously. The trick is to make sure those assumptions are correct, by having operations do what you would expect them to do.
 OdessE writes:
 After I wrote
 it, I had to examine it 4 times to make sure I had it correct,
 with all the braces and the order of the arguments.

I had no such burden.

Good for you, but you are contradicting yourself with this cowboy-coder comment. So if you know what it means than it is not a problem eh?

Nope, it's not a problem because you can easily remember what it means as well. Most importantly the colon at the front of the label is your cue that unusual behaviour is taking place.

Excuse me, what colon? I was talking about an example with named functions, that is why I was mentioning how the braces were confusing to me: MyClass result.Assign(MyClass::.Add (Var1, MyClass::Multiply (Var1,Var3))); That was the function I was talking about. Where is the colon?
 Odesse writes:
 You still didn't say that

 MyClass result.Assign(MyClass::.Add (Var1, MyClass::Multiply (Var1,

 is more readable than

 MyClass result = Var1 + Var1 * Var3;

 probably because it just isn't.

Yes, the first statement is more readable than the second because in the case of the second statement we are not told what + and * do.

Yes we are, by our math teachers when we go to school. You know what plus is supposed to do. You also know what Add() is supposed to do. If they really do it is a different matter. If you can't grasp what + is supposed to do, why would Add() be more clear? I don't know what House1 = House2 + House3; is supposed to do, but then again I don't know what House1.Assign (House::Add (House2, House3)); is supposed to do either. Do you? Maybe add the windows in the house?
 We only know that they perform some unknown operation, and that operation
 depends on the variable types which are not specified.

In D the type of all variables is always specified. The meaning of the Add() operation on the other hand might not be specified, since it is not required by the languag that it is documented. All we know is that it is a static function which takes two arguments of a certain type and returns another argument of that same type. But we also know that of the + operator. What is the difference?
 Hence we can say nothing about the second function.

Nor about the first. All we can do is read the documentation, use our common sense in interpreting well known symbols or variable names and look at the definition or implementation of the functions involved.
 However in the case of :+ and :* there is a 1:1 correspondance between
 function and operator label so knowing that

 :* = Myclass::Multiply(Var1,Var3)
 :+ = Myclass::Add(Var1,Var3)

 We know everything we need to know about the equation.

No we don't. We still don't know what Multiply() does, at least not when we "may not assume anythign" like you say. We just added an extra layer of complexity. I now have to remember that :* calls Multiply and find out what Multiply does.
 It's really quite simple.  I fail to see your objection.

Strange. I see your objections, I just don't agree with them. Do you mean to say you really don't understand what is being said?
 The problem with operator overloading is that it can be highly


 What Isn't highly confusing however, and what does provide the





 benefit
 is providing the ability to create your own operators.


OdessE writes:
 Mmmm.... So you don't understand what A + B or C * D
 means, but you do understand all of the very complex
 operators that exist in math today, as well as the ones that
 I personally come up with?

Clearly no one can, since the meaning of + and * are dependent on the

 of A, B, C and D.


Odesse writes:
 And clearly no one can now the meaning of .+ and .*

Since there is a 1:1 correspondance of label and funtion, you consult

 opcode table.

Great all these tables.
 You can not do this with + and * since there are no visual clues that +

 * are
 doing anything outside their ordinary meaning.

 a = b + c
 d = e + f

 In your inferior system of operator overloading the first example above

 be
 doing a simple addition,. while the second could be adding a graphic to a
 web page an
 uploading the result to a server.

 Quite foolish.

It could also format your harddisk. But so could your :+ operator. There are some visual cues that the operator is overloaded, because the parameters used with it are non-standard. The operator itself looks the same, but so it should. You are performing a standard operation with it, you are just performing it on non-standard parameters. Hence the visual cue should come from the parameters.
 Odesse writes:
 At least with normal operators I know what they usually do and
 have a reference in math or other languages to draw experience on.

And you can still use that by creating new operators with names similar to the existing operators. :+ in place of + for example.

They are confusing. Especially the fact that everyone can, and will, define different operators to perform the same operation on the same types of variables (say vectors, strings, the boundschecked pointer you would like) is going to cause a lot of confusion.
   But you have the advantage of creating new operators with more
 appropriate labels as well

   For example :dot or :cross for dot and cross products  If the colon were
 more visible
 on this screen I would have used colon period, for dot product and colon x
 for cross product.

? You are already using the colon. :cross looks like a function, not an operator. What is the use of operators if they have names? You might as well define :add instead of +. The idea behind operator overloading is to use the notation of the problem domain. If you are describing a mathematical addition you want to use the mathematical operator to describe that operation.
   So all of the advantages of operator overloading exist while all of the
 failures of C++ style operator
 overloading can be avoided.

None of the advantages exist. You lose the biggest advantage, the fact that you can use operators from math to represent the mathematical operations you want to perform. What you are left with is essentialy a way to hide descriptive function names behind strange self-defined and thus arbitrary symbols such as :V+. Just a shame you defined :V+ for Vector math as in matrices and vectors, while someone else defined it to concatenate java style vectorss. On the other hand, I defined the addition for math vectors as :+ because it was the only one I needed, while you thought that one was more appropriate for your bounded pointer. Do you really mean to say you don't see how this might cause confusion?
   Operator overloading is clearly inferior.
 .

 It depends on what A and B are.and what you are trying to do.  Perhaps



 and
 B are objects, the == syntax can have three equally appropriate


 A
 is numerically identical to B,  A is functionally identical to B, A



 B
 are the same object.

 With one equal sign, how do you intend to distingish between these



 poetntial meanings?  How do you intend to implement more than one of


 at
 a time?

 I await your response.



To check if the objects were one and the same, you would compare the references, not the object they are pointing to. To check wheter the objects contain the same information you would check the objects themselves.
 Odesse writes:
 I don't really see how Cmp solves these issues better then operator
 overloading.
 And if you compare two numbers to see if they are equal, do you try to

 out if the are the same instance of an int? Draw from experience.

That may very well be a requirement yes. That int may very well be a semiphore used for synchronization, or used by the program to tell if it is looking at an instance of itself. Once again I fail to see your complaint.

How do you do this in C/C++? You mean int a; int *pa int *pb; pa = &a; pb = &b; if (*pa == *pb) // same number in instances of int if (pa == pb) // same instance of int I don't see why operator overloading would make this more difficult. Anyhow, you are not comparing the same objects. In the first case you are comparing two ints. In the second case you are comparing two references or pointers to ints. By definition, each instance of an object is a unique entity. When you use classes, the operator to compare the pointers to the classes would be automatically defined, so you compare using that. To compare not the pointers or references, but the objects themselves, you need to use Cmp() or an overloaded operator. Your argument does not hold, simply because you are saying that the comparison operator can have different meanings when applied to the same type, when in the example you give they are actually applied to different types, objects (the ints) and references to these objects. So it makes sense that the same operation applied to variables of different types yields different results.
 Odesse writes:
 int A = 10;
 int B = 10;
 int C = 0;

 if (A == B)
    C = A;
 B = 5;

 What value does C have?

If this langauge allows all operators to be overloaded even for the base types then we do not know the answer because somewhere elsewhere in the program the operators may have hand their meaning altered.

No one is saying that operators should be overloaded for operations between base types, so we *do* know what value C has. You are avoiding the conclusion. If we compare objects we want to know if they contain the same information. If we want to know if two references point to the same object, we compare the references, not the objects themselves. These are two different operations on two different types, hence they yield two different results. -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Feb 07 2002
parent reply "Immanuel Scholz" <digital-mars kutzsche.net> writes:
"OddesE" <OddesE_XYZ hotmail.com> schrieb im Newsbeitrag
news:a3uudo$2amb$1 digitaldaemon.com...
 "D" <s_nudds hotmail.com> wrote in message
 news:a3r33g$28jj$1 digitaldaemon.com...
 OddesE <OddesE_XYZ hotmail.com> wrote in message
 news:a3ph43$61j$1 digitaldaemon.com...
 Consider this pieces of code:

 define op var1 ** var3 = MyClass::Multiply(Var1,Var3)
 define op var1. *+ var3 = MyClass::Add(Var1.Var3)
 define op var1 #* var3 = MyClass::Multiply(Var1,Var3)
 define op var1. #+ var3 = MyClass::Add(Var1.Var3)
 define op var1 $* var3 = MyClass::Multiply(Var1,Var3)
 define op var1. $+ var3 = MyClass::Add(Var1.Var3)
 define op var1  * var3 = MyClass::Multiply(Var1,Var3)
 define op var1.  + var3 = MyClass::Add(Var1.Var3)
 define op var1 &* var3 = MyClass::Multiply(Var1,Var3)
 define op var1. &+ var3 = MyClass::Add(Var1.Var3)

 MyClass::result =  Var1 *+ Var1 ** Var3
 MyClass::result =  Var1 #+ Var1 #* Var3
 MyClass::result =  Var1 $+ Var1 $* Var3
 MyClass::result =  Var1  + Var1  * Var3
 MyClass::result =  Var1 &+ Var1 &* Var3

Yup I do see difficulty with your code. It's difficult to read because

 have
 chosen to define the same function for multiply and add a total of 5


I actually did not do that. 5 other programmers did that. Some of them were on other teams, others were with other companies that we use libraries of. All these declarations were in different files and were part of different libraries. Unfortunately they all do the same thing, they all add two strings. All these programmers noticed the lack of string support in language X but, since it did include adding new operators, they invented one of their own. Unfortunately I have to memorize them all, or find different libraries.

Hm. Without either operator overloading or adding new ops, I have seen this issue again. There are plenty of functions meaning the same, but spelling different, even in a library from the same concern: CArray::RemoveAll CListCtrl::DeleteAllItems CMap::RemoveAllItems ( I believe? Couldn't remember) ... These are exact the same problem if you have none of both, operator overloading or new operators (And the problem is worse, since "size" and "Size" are different things ;-) There could be a String:: concatenate add concat cat All with proper, logical meanings (and CaSEs).
 Very poor programming practice.
 Consider the equivalent defined only once....
 define op var1 ** var3 = MyClass::Multiply(Var1,Var3)
 define op var1. *+ var3 = MyClass::Add(Var1.Var3)

You try to convince hundreds of programmers to use your style... Math already has defined these operators, but no, you can't use those...Invent some of your own...

Maybe operator defining is just simple a step away from functional call to the infix-notation of functions. There were really times, I wanted to have something like: midsum = a :avg: b :avg: c :avg: d; instead of midsum = a.avg(b.avg(c.avg(d)));
 MyClass::result =  Var1 :+ Var1 :* Var3

 Yes, quite readable now that the purposeful obfuscation has been


 What does the : mean?
 Where is the standard? What prevents other companies from using
 entirely different standards? How am I supposed to remember all
 this? I am not as good as you at memorizing tables with useless data...

I agree with "D" (exept his name... "D"... can I call you troll? ;-). It is surely a very very powerful feature, if you can completly hide a new datatype to the user, providing him with the same operators he always used. If they are implemented good, and no mistake is done, the user of your classes can become a very good feeling. But this is not reality. Too much I saw bad implementations of operators, since someone either used them in different meaning. --------------------------- 1. Bad case: Someone thinks it looks pretty: As example I saw once the operator << overloaded in a stack- implementation to push something onto the stack and >> to pop something. The author was very proud of this nonsens: p << 4; Looks good, if you know that << is push, but is terrible, if you do not and think << has to be bitwise-shift-left or something like a stream-operator (you see, even in the C++-Standardlibrary there are an inconsistenz use of <<). --------------------------- 2. Bad case: Someone misunderstood the real meaning of an operator: The equality-operator is a big problem to overload (as stated somewhere above). Should it equals to object identity or to value identity? Another big thing is operator new. Maybe 8 out of 10 implementations of this operator I saw turned out to have at least one bug in them. It is powerful, but dangerous! So I really do not recommend to allow operator overloading (although I use it really frequently in C++ ;-) Now to adding new operators: The point is, they cannot harm existing operators, so there could no confusing things. This meens, the user cannot be fooled to think, he does use a built-in type but is using a class you support. This has dis- but also has advantages. But you can, if you do it right, give almost the feeling to the user, that it is a built-in type. He only has to remember to add, e.g. a ":" before the usual operators. And second, you can define your shortcuts, for which they are no operator currently exist, as example to push to the stack, you could use p <=- 2; and p -=> a Looks pretty nice too, but cannot be mistaken with << and >>.
 Great, all these lists and tables. Let's name our variables var1, var2 and
 var3,
 then keep a list of what they mean.

This would be as stupid as defining :!2$-> of two strings to concatination. I think you can find bad variable names as you can find bad operator names. Maybe it is easier to find bad variable names, but this doesn't affect the thing, that a :+ b :+ c is always more readable than a.add(b.add(c)) (at last IMHO)
 No standards are needed.   :V+ is a nice enough name for vector add.

Your opinion. I don't agree. I still don't mean what the colon stands for. I could guess at the V, but I don't like guessing what code does, I like knowing so from experience and common sense.

Here I have to agree to Odysseus, err, Odesse ;) I think code conventions will do the thing, now or later.
 Matrix multiplication might could be indicated by :M* or :MtxMul, or
 whatever
 name the programmer sees fit to use.

Ah yes, :MtxMul... Starts to sound a lot like a regular function name doesn't it? What is the point?

The point (to me, at least) is the INFIX-NOTATION! It is even much better to write a add (b add c) mul d Than a.add(b.add(c).mul(d)) Maybe because I never coded in Lisp before, but I think many other coders will agree with me.
   Primarily because as you yoursef showed in another thread,
 they aer forced to by the limited number of existing operators.

Yes, but why replace the existing ones with substitutes that do exactly the same, such as :V+ ?

Because they cannot be confused with ordinary once. I think this is a really important face (and THE fact, that Walter did not include operator overloading in the draft)
 Odesse writes:
 Who keeps me from doing this:

 define op var1 .* var3 = MyClass::Add (Var1,Var3)
 define op var1. .+ var3 = MyClass::Multiply (Var1.Var3)

 MyClass::result =  Var1 .+ Var1 .* Var3

Absolutely nothing. Do you regularly program in that manner?

I don't, but you keep saying that programmers are clueless and do such things. I am asking you how your method prevents this.

It prevent this not. But overloading did not prevent the user from Foo Foo::operator+(Foo f) { return value * f.value; } The exception is, that you see, that the operator .+ is user-defined (note the point before the +) and you do not see that same from operator+, if not explicit looking at the types. So you generally do not expect a problem.
 1. Existing operators do not change their meaning and therefore
     all lines containing existing operators can be taken at face value
     rather than being suspect of hiding some unsuspected behaviour.

With operator overloading (if used right) they don't change their meaning either. + means to add something. You are just changing the something you want to add. You could define operator+ to multiply it's parameters ofcourse, but you could do that using any of the constructs we are talking about.

For operator+ it might be clear. But as example operator<<. Is it a shift-left or a output-into-stream? Such operators already received more than one meaning, and it will become more (as I showed above on "stack push")...
 2. There is a 1:1 relationship between operator and function which


     the programmer to use a simple operator table to figure out what a
 specific
     equation means

I don't like those tables, and with normal operators you don't need them, you already know what + means.

What means equal to you? bitwise equal or object identity (e.g. it IS the same reference)? As example to the impact: If you say bitwise, you are not Java-conform. Java-coder expect this to be equality of object identity.
 3. I recommend that all new operators have the same precedence. Hence
 there
     is no confusion in the order of operations, and no unnatural
 consequences to
    what would otherwise be automatic reordering.


Hm, I disagree. What is the disadvantage to intreduce precedence-values? E.g. they range from 0 to 100?
 A yes:

 Assuming a class int64 with operators defined for adding
 and multiplication:

 int64 a, b, c;

 a := a :+ b :* c;

 Now you will get different results then you would expect from
 plus and multiply operations... It just doesn't make sense that
 all math knowledge becomes invalid when using operators.

Odesse is right.
 4. New operators would provide visual cues that readily distinguish them
 from
     existing operators, thereby allowing the programmer to readily
 identify
 new program
     behaviour.

The behaviour for + is not new, it is still adding two entities. You are just allowing new types to be added.

This the last time I will write this: It is not clear. Maybe in most cases for +. But not for all other operators. Not enough, you did not expect errors in +, because you are fooled that + is build-in. But they can be errors in operator+
 Yet the first equal under your regime of operator overloading would have


 meaning that is entirely
 different than the second equal symbol,.

Right, entirely different. No relation whatsoever. Are you kidding me? I am assigning one variable to another, since when does the assignment of objects of a class have nothing in commom with assigning integers or floats? Should we also use different operators for addition of all basic types? The have "nothing in common" after all...

Assignment is not that basic: If you have a class with a pointer in it, would you copy the simple pointer, so that both classes refer to the same object or would you also copy the data behind the pointer? This is a common problem, you cannot decide generally. It make even be true, that you need both behaviour in the same programm. Some coder build then member functions like .clone(). Some do not. You do not surely know, what the class is doing you use if you call operator=...
 Odesse writes:
 You still didn't say that

 MyClass result.Assign(MyClass::.Add (Var1, MyClass::Multiply (Var1,

 is more readable than

 MyClass result = Var1 + Var1 * Var3;

 probably because it just isn't.

Yes, the first statement is more readable than the second because in the case of the second statement we are not told what + and * do.

Yes we are, by our math teachers when we go to school. You know what plus is supposed to do. You also know what Add() is supposed to do. If they really do it is a different matter. If you can't grasp what + is supposed to do, why would Add() be more clear? I don't know what House1 = House2 + House3; is supposed to do, but then again I don't know what House1.Assign (House::Add (House2, House3)); is supposed to do either. Do you? Maybe add the windows in the house?

Yeah. operator overloading can be REAL powerful. I like it. It is good. But only as long as you use it right. I think this weapon is much too powerful. New operators don't have some of the problems of overloading, or at least the user is aware, that there might be Problems.
 Odesse writes:
 And clearly no one can now the meaning of .+ and .*

Since there is a 1:1 correspondance of label and funtion, you consult your opcode table.

Great all these tables.

Hm. I would not think that .+ is a multiplication. It looks somelike a addition. I recognized this without a table...
 You can not do this with + and * since there are no visual clues that +

 * are
 doing anything outside their ordinary meaning.

 a = b + c
 d = e + f

 In your inferior system of operator overloading the first example above

 be
 doing a simple addition,. while the second could be adding a graphic to


 web page an
 uploading the result to a server.

 Quite foolish.

It could also format your harddisk. But so could your :+ operator.

Yes, but those could NOT the build-in + operator for build-in types. And thats the point the troll wanted to make.
 There are some visual cues that the operator is overloaded, because
 the parameters used with it are non-standard. The operator itself
 looks the same, but so it should. You are performing a standard
 operation with it, you are just performing it on non-standard
 parameters. Hence the visual cue should come from the parameters.

But you do not see that "a" is a class. It could be a integer?
 At least with normal operators I know what they usually do and
 have a reference in math or other languages to draw experience on.

And you can still use that by creating new operators with names


 to the existing operators.  :+ in place of + for example.

They are confusing. Especially the fact that everyone can, and will,

 different operators to perform the same operation on the same types of
 variables (say vectors, strings, the boundschecked pointer you would
 like) is going to cause a lot of confusion.

This is right. One of the disadvantages of new operators. But anyway, it is a disadvantage of functions too. Count how many similar functions there are to copy memory...
   But you have the advantage of creating new operators with more
 appropriate labels as well

   For example :dot or :cross for dot and cross products  If the colon


 more visible
 on this screen I would have used colon period, for dot product and colon


 for cross product.

? You are already using the colon. :cross looks like a function, not an operator. What is the use of

 if they have names? You might as well define :add instead of +. The idea
 behind operator overloading is to use the notation of the problem domain.
 If you are describing a mathematical addition you want to use the
 mathematical operator to describe that operation.

And infix. You cannot write infix-notation with function calling convention...
 It depends on what A and B are.and what you are trying to do.




 A
 and
 B are objects, the == syntax can have three equally appropriate
 meanigns.
 A
 is numerically identical to B,  A is functionally identical to B, A
 and
 B
 are the same object.

 With one equal sign, how do you intend to distingish between these
 three
 poetntial meanings?  How do you intend to implement more than one of
 them
 at
 a time?

 I await your response.



To check if the objects were one and the same, you would compare the references, not the object they are pointing to. To check wheter the objects contain the same information you would check the objects themselves.

You only have one operator==. Maybe you decide, somehow, that equality by value is what you mean. But somebody else (maybe a java-guru) did expect this as the last thing in his mind. Who has right? C++ recommends using compare by value, other similar languages does not.
 How do you do this in C/C++?
 You mean

 int a;
 int *pa
 int *pb;

 pa = &a;
 pb = &b;

 if (*pa == *pb)     // same number in instances of int
 if (pa == pb)         // same instance of int

 I don't see why operator overloading would make this more difficult.

Comparing the instances is much more faster than comparing the values. If you write a class which time is essential, you may want to compares it by instance (So you do not have to call operator= for each class member). But maybe other users of your class expect it comparing by value? Although in some languages, as I stated above, comparing by instance is the normal way, and using a .equals() is the unusual... There are NO well-known standards uppon all operators.
 Odesse writes:
 int A = 10;
 int B = 10;
 int C = 0;

 if (A == B)
    C = A;
 B = 5;

 What value does C have?

If this langauge allows all operators to be overloaded even for the base types then we do not know the answer because somewhere elsewhere in the


 the operators may have hand their meaning altered.

No one is saying that operators should be overloaded for operations between base types, so we *do* know what value C has. You are avoiding the conclusion. If we compare objects we want to know if they contain the same information. If we want to know if two references point to the same object, we compare the references, not the objects themselves. These are two different operations on two different types, hence they yield two different results.

Logical ideas and abstracts may not be the reality. The operator overloading IS still a big pool of errors that do more harm than good. Imi -- Oh dear, its 4:30am, I hope my better side don't kill me for usenetting so long...
Mar 06 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message
news:a66n7e$1nne$1 digitaldaemon.com...

 So I really do not recommend to allow operator overloading
 (although I use it really frequently in C++ ;-)

Hey hey hey, stop!.. let it be there, just leave it to us gurus =)
 This meens, the user cannot be fooled to think, he does use
 a built-in type but is using a class you support. This has dis- but
 also has advantages.
 But you can, if you do it right, give almost the feeling to the user,
 that it is a built-in type. He only has to remember to add, e.g. a ":"
 before the usual operators.

But who'd stop some coder from overloading operator *+-/ then? And what would it mean? Your guess...
 a :+ b :+ c

 is always more readable than

 a.add(b.add(c))

 (at last IMHO)

And a ~ b ~ c would be even more readable, IMO.
 It is even much better to write

 a add (b add c) mul d

 Than

 a.add(b.add(c).mul(d))

 Maybe because I never coded in Lisp before, but I think many
 other coders will agree with me.

In general, I agree. So user-defined operators are great, but let's forbid them to be usual identifiers. So: Vector operator cross (Vector a, Vector b) { ... } a = b cross c;
 Because they cannot be confused with ordinary once. I think
 this is a really important face (and THE fact, that Walter did not
 include operator overloading in the draft)

In fact, the programmer very frequently doesn't care whether it is the "ordinary" operator or a user-defined... all he wants to know is that a + b will always add b to a, be they integers, vectors, matrices, or dates...
 For operator+ it might be clear. But as example operator<<.
 Is it a shift-left or a output-into-stream?  Such operators already
 received more than one meaning, and it will become more (as I showed
 above on "stack push")...

Walter clearly stated that, if operator overloading is to be implemented, things like using << for output will be strictly prohibited by him personally. I second that. =)
 This the last time I will write this: It is not clear. Maybe in most cases
 for +.
 But not for all other operators. Not enough, you did not expect errors
 in +, because you are fooled that + is build-in. But they can be errors in
 operator+

There can be errors in operator :+ as well. Also, all operators have rather strict meaning. If only we get the "input" and "output" operators in D, it would be great!
 You do not surely know, what the class is doing you use if you
 call operator=...

I suggest forbid overloading = at all. = should copy references, never objects.
Mar 06 2002
parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a66s4k$1ph2$1 digitaldaemon.com...
<SNIP>
 In general, I agree. So user-defined operators are great,
 but let's forbid them to be usual identifiers. So:

     Vector operator cross (Vector a, Vector b) { ... }
     a = b cross c;

I agree with this. My standpoints in this discussion have become rather settled, and I am afraid I won't easily change them anymore, unless someone comes up with some really good and new argument. 1. I support operator overloading for standard operators. As to operators == and =, I agree that there could be ambiguity between comparing / assigning by reference or by value, but this could be resolved: MyClass a, b; *a = *b; if (*a == *b) // By value a = b; if (a == b) // by reference, or &a = &b; if (&a == &b); Whatever, essentially a notation that says by reference or by value is needed. Assignment by value means deep copy, otherwise destroying one object will render both invalid, not what you would expect in 99% of the cases. -, +, /, and * are usually well defined and all you need. Operators such as new, delete and << and >> could be forbidden. 2. I support infix notation with precedence for arbitrary functions, this will allow for creating new operator-like behaviour and is all you need most of the time for special functions such as dot product and cross product. I agree with Pavel that normal function naming rules should be applied, I am against using :+: to add two entities, because it can, and will lead to hundreds of different versions of plus operators all doing the same but looking very different. Immanuel was saying in a previous post that this can also be done with normal functions, but that just proofes my point. :+: offers no significant advantages over add because there is no standard there either. Math however is as standard as standards get, and so is +. Please do not allow inventing arbitrary symbols using combinations of :, !, , #, $, %, +, -, /, * etc. to define new operators, it will not make programming more easy at all! -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Mar 07 2002
next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a68s84$872$1 digitaldaemon.com...

     Whatever, essentially a notation that says by reference or by
     value is needed. Assignment by value means deep copy,
     otherwise destroying one object will render both invalid, not
     what you would expect in 99% of the cases.

You don't actually "destroy" anything in D. Even operator delete doesn't do that if it isn't safe, AFAIK - or am I wrong, Walter?
     -, +, /, and * are usually well defined and all you  need.
     Operators such as new, delete and << and >> could
     be forbidden.

I would leave << and >> there for things like bignum. new and delete should be restricted. Also, I'd add two more built-in operators, "in" and "out". These could be used for streams, stacks, queues, and anything similar that allows to put values in and take them out: int foo, bar; stdout out "Hello, world!\n" out "foo = " out foo out \n; stdin in foo in bar;
Mar 07 2002
next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel Minayev wrote:

 "OddesE" <OddesE_XYZ hotmail.com> wrote in message
 news:a68s84$872$1 digitaldaemon.com...

     Whatever, essentially a notation that says by reference or by
     value is needed. Assignment by value means deep copy,
     otherwise destroying one object will render both invalid, not
     what you would expect in 99% of the cases.

You don't actually "destroy" anything in D. Even operator delete doesn't do that if it isn't safe, AFAIK - or am I wrong, Walter?

Walter may have to correct my memory here, but I think that delete forces destruction of the object. The reason I think that is that I remember arguing with Walter about it, because I thought that it was a bad idea :) -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Mar 08 2002
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel Minayev wrote:

 Also, I'd add two more built-in operators, "in" and "out".
 These could be used for streams, stacks, queues, and anything
 similar that allows to put values in and take them out:

If you allow infix function calls, then they're not even operators. You just define int stdio::out(char[]) to write. For the input side, you have to change the usage a little to get pointers, but then you define: stdio *stdio::in(int*); stdio *stdio::in(char[]); etc. Maybe I'm missing something...but it seems like it should work, AFAIK. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Mar 08 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C88F341.A4FB9F7E deming-os.org...

 If you allow infix function calls, then they're not even operators.  You
 just define
     int stdio::out(char[])

Could be. But I thought a separate syntax for operators would be better... well, actually I don't care. Let's leave this to Walter to decide. =)
 to write.  For the input side, you have to change the usage a little to
 get pointers, but then you define:
     stdio *stdio::in(int*);
     stdio *stdio::in(char[]);
     etc.

 Maybe I'm missing something...but it seems like it should work, AFAIK.

Er... "stdio" is already a pointer. Remember, there are no stack objects in D!
Mar 08 2002
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel Minayev wrote:

 to write.  For the input side, you have to change the usage a little to
 get pointers, but then you define:
     stdio *stdio::in(int*);
     stdio *stdio::in(char[]);
     etc.

 Maybe I'm missing something...but it seems like it should work, AFAIK.

Er... "stdio" is already a pointer. Remember, there are no stack objects in D!

Right. That function I proposed was something that RETURNS a pointer...so that your chain calls could work (it returns 'this'): stdin in &foo in buf; Of course, this would only work if the infix funciton notation allows pointers on the left side. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Mar 08 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C8909C6.3DEB9FBF deming-os.org...

 Right.  That function I proposed was something that RETURNS a pointer...so
 that your chain calls could work (it returns 'this'):
         stdin in &foo in buf;

No, I mean that since StdIn is a class, you don't need to use * to state it as a pointer: class StdIn { StdIn read(out int n) // returns a reference to StdIn { ... return this; } } StdIn stdin; stdin read foo read bar read etc; Also, "in" and "out" are reserved D keywords, so they can't be used as function names.
 Of course, this would only work if the infix funciton notation allows

 on the left side.

I'd be pretty happy to have built-in input/output operators and the ability to overload them, for now.
Mar 08 2002
parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel Minayev wrote:

 "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
 news:3C8909C6.3DEB9FBF deming-os.org...

 Right.  That function I proposed was something that RETURNS a pointer...so
 that your chain calls could work (it returns 'this'):
         stdin in &foo in buf;

No, I mean that since StdIn is a class, you don't need to use * to state it as a pointer:

Oops, you're right :(
 Also, "in" and "out" are reserved D keywords, so they can't be
 used as function names.

Oops, right again. :( -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Mar 08 2002
prev sibling parent reply "Immanuel Scholz" <digitals-mars kutzsche.net> writes:
"OddesE" <OddesE_XYZ hotmail.com> schrieb im Newsbeitrag
news:a68s84$872$1 digitaldaemon.com...
     Whatever, essentially a notation that says by reference or by
     value is needed. Assignment by value means deep copy,
     otherwise destroying one object will render both invalid, not
     what you would expect in 99% of the cases.

Hm, I tend to have pointers in classes without the need to destroy them at ~this, because the main meaning of pointer is (for me), a reference to an object, the class did not own.
     -, +, /, and * are usually well defined and all you  need.
     Operators such as new, delete and << and >> could
     be forbidden.

I agree. If D allows only to overload "safe" operators, maybe we get some of the advantages together. Whoever, I recommend to allow defining other infix-notation-operators, because this can become VERY handy. As example, I could not believe, that stream-output without infix notation would let to any happy coder ;-) Imi
Mar 08 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message
news:a6a6n6$q8a$1 digitaldaemon.com...

 I agree. If D allows only to overload "safe" operators, maybe we
 get some of the advantages together. Whoever, I recommend
 to allow defining other infix-notation-operators, because this
 can become VERY handy.
 As example, I could not believe, that stream-output without infix
 notation would let to any happy coder ;-)

Well if D would support variants (or object packaging as seen in C#), and paramarrays, it could be done like in Pascal: stdout.print("Hello, world!", 666, 123.456); But I guess operator overloading is a better solution. Some kind of operators, like "in" and "out" I've suggested in earlier post, or maybe something like <- and -> ? char[] name; stdin -> name; stdout <- "Hello, " <- name <- "!\n";
Mar 08 2002
parent reply "Immanuel Scholz" <digitals-mars kutzsche.net> writes:
"Pavel Minayev" <evilone omen.ru> schrieb im Newsbeitrag
news:a6a95d$r51$1 digitaldaemon.com...
 "Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message
 news:a6a6n6$q8a$1 digitaldaemon.com...

 I agree. If D allows only to overload "safe" operators, maybe we
 get some of the advantages together. Whoever, I recommend
 to allow defining other infix-notation-operators, because this
 can become VERY handy.
 As example, I could not believe, that stream-output without infix
 notation would let to any happy coder ;-)

Well if D would support variants (or object packaging as seen in C#), and paramarrays, it could be done like in Pascal: stdout.print("Hello, world!", 666, 123.456); But I guess operator overloading is a better solution. Some kind of operators, like "in" and "out" I've suggested in earlier post, or maybe something like <- and -> ? char[] name; stdin -> name; stdout <- "Hello, " <- name <- "!\n";

-> has a different meaning. Although it is not used in D, I prefer another symbol. Maybe -=> or >>> ?
Mar 08 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message
news:a6ainp$umk$1 digitaldaemon.com...

 -> has a different meaning. Although it is not used in D, I prefer another
 symbol.

 Maybe -=> or >>> ?

I remember >>> was unsigned shift. -=> just looks somewhat weird. And what's the problem with -> ? Yes, it had a special meaning in C, but it's not used in D now, and it's quite mnemonic - an arrow pointing "to" or "from" the stream...
Mar 08 2002
parent reply "Immanuel Scholz" <digitals-mars kutzsche.net> writes:
"Pavel Minayev" <evilone omen.ru> schrieb im Newsbeitrag
news:a6amrk$1091$1 digitaldaemon.com...
 "Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message
 news:a6ainp$umk$1 digitaldaemon.com...

 -> has a different meaning. Although it is not used in D, I prefer


 symbol.

 Maybe -=> or >>> ?

I remember >>> was unsigned shift. -=> just looks somewhat weird.

Huh... Yes. -} and {- ? or [- and -] or (- and -) ... ? :-)
 And what's the problem with -> ?  Yes, it had a special meaning
 in C, but it's not used in D now, and it's quite mnemonic -
 an arrow pointing "to" or "from" the stream...

The Problem I would have is, that other coder would begin implementing operators after meanings, they saw before, and not after the meaning in the new language. If you are able to overload <<, I bet, some coder disagree with D-conventions and overload << to stream-output... Imi, the paranoic one. (The world is bad... %-) )
Mar 08 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message
news:a6an6p$10ft$1 digitaldaemon.com...

 The Problem I would have is, that other coder would begin implementing
 operators after meanings, they saw before, and not after the meaning in
 the new language. If you are able to overload <<, I bet, some coder
 disagree with D-conventions and overload << to stream-output...

...unless the author of the language and the community STRONGLY DISCOURAGES such use of operators << and >>. Such guys could overload << and >> for themselves, but hopefully libraries which define these operators for such purposes will be boycotted. Also, the simplest way to enfore using operators other than << and >> would be to use their D replacements in Phobos. If streams would use, say, <- and ->, and most programs use streams for some purpose, there probably wouldn't be anybody stupid enough to turn against the mainstream and overload << and >> just to follow C++ conventions... if every D user from the very beginning knows that <- is output and -> is input, it will be very hard to convince them to use some other scheme... Also, define -> to be a _binary_ operator, and there is no way to overload it so it is the same as in C. =)
Mar 08 2002
next sibling parent reply Roland <rv ronetech.com> writes:
Pavel Minayev a écrit :

 if every D user
 from the very beginning knows that <- is output and -> is input,
 it will be very hard to convince them to use some other scheme...

while you are reconsidering the way stream are implemented, i personally 'feel' better -> as an output and <- as an input..(sorry for the trouble). roland
Mar 08 2002
parent Russell Borogove <kaleja estarcion.com> writes:
Roland wrote:
 Pavel Minayev a écrit :
  
if every D user
from the very beginning knows that <- is output and -> is input,
it will be very hard to convince them to use some other scheme...

while you are reconsidering the way stream are implemented, i personally 'feel' better -> as an output and <- as an input..(sorry for the trouble).

<dripping_sarcasm> Clearly this potential confusion is a compelling argument for eliminating operator overloading, I/O, and the characters '-', '>', and '<' from the language. </dripping_sarcasm> (This isn't at all intended as an attack on your preferences for I/O operators, Roland, but as a snipe at the operator overloading fascists.) -RB
Mar 08 2002
prev sibling parent "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a6anls$10lr$1 digitaldaemon.com...
 ...unless the author of the language and the community STRONGLY
 DISCOURAGES such use of operators << and >>. Such guys could
 overload << and >> for themselves, but hopefully libraries which
 define these operators for such purposes will be boycotted.

I remember back when C was new and Pascal was the old guard. Many C programmers would write: #define BEGIN { #define END } and other such to make their C look like familiar Pascal'ish. After a couple years of that, it became clear to the entire C community that such was the wrong way to go about programming in C, and the practice disappeared under a torrent of ridicule. It's only natural that programmers moving from C++ to D will start out by programming C++ in D (after all, it's long been recognized that you can write FORTRAN in any language, so why not C++ in D?), and only after a while with the C++isms will get discarded. I myself sometimes catch myself doing things the C++ way in D, and have to go back and rewrite it. For example, I was using memset() when an array assignment was the D way.
Mar 10 2002