www.digitalmars.com         C & C++   DMDScript  

D - new properties for dynamic arrays

reply "Sandor Hojtsy" <hojtsy index.hu> writes:
I would like to come up again with an issue already discussed in some
details.
What stops us from (also) having

str4 = str1.left(5) ~ str2[3..4] ~ str3.right(6);

instead of

str4 = str1[0..4] ~ str2[3..4] ~ str3[str3.length-6..str3.length-1];

For me it seems much more intuitive, and easy enough to implement. Using the
"right" property can even be faster than slicing, due to the absence of
multiple indirections.

Yours,
Sandor
Jul 09 2002
next sibling parent "Sean L. Palmer" <seanpalmer earthlink.net> writes:
That's not a bad idea!

We could also have some kind of .mid property that has a more natural syntax
than for array slicing.  Such as pos and count, and count would maybe be
rangechecked against the available size.

You could call the .left property .first or the .right property .last also,
to make it more generic and intuitive (not all strings read "left to right"
especially in Chinese etc)

Sean


"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:agec01$2alu$1 digitaldaemon.com...
 I would like to come up again with an issue already discussed in some
 details.
 What stops us from (also) having

 str4 = str1.left(5) ~ str2[3..4] ~ str3.right(6);

 instead of

 str4 = str1[0..4] ~ str2[3..4] ~ str3[str3.length-6..str3.length-1];

 For me it seems much more intuitive, and easy enough to implement. Using

 "right" property can even be faster than slicing, due to the absence of
 multiple indirections.

 Yours,
 Sandor

Jul 09 2002
prev sibling parent reply "anderson" <anderson firestar.com.au> writes:
Looks like a good idea.  I've always like how that could be done similarly
in VB. It should be part of the standard.

Of coarse you could always invent your own and write it like....

str4 = left(str1, 5) ~ str2[3..4] ~ right(str3, 6);

On a slightly different note.
Perhaps there could also be a way of creating your own attributes/properties
for arrays (or any type for that matter).  Perhaps that could be something
included in Generics when it's implemented. Or perhaps we should just stick
to using classes.

Hmmm....

Or perhaps the property (getters and setters) syntax in D could be
extended...

char[] left(char[] in String, int in value) {...}

Would be equate to...

    string2 = left(string, 5);
and ...
    string2 = string.left(5);

And the setter (if needed)

    void left(char[] in String, int in value) {...}

    string.left(5) = "The first 5 letters of this sentence.";

Or something along those lines...(I sense problems with what I just wrote).


"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:agec01$2alu$1 digitaldaemon.com...
 I would like to come up again with an issue already discussed in some
 details.
 What stops us from (also) having

 str4 = str1.left(5) ~ str2[3..4] ~ str3.right(6);

 instead of

 str4 = str1[0..4] ~ str2[3..4] ~ str3[str3.length-6..str3.length-1];

 For me it seems much more intuitive, and easy enough to implement. Using

 "right" property can even be faster than slicing, due to the absence of
 multiple indirections.

 Yours,
 Sandor

Jul 09 2002
parent reply "Sandor Hojtsy" <hojtsy index.hu> writes:
"anderson" <anderson firestar.com.au> wrote in message
news:agga0i$1mop$1 digitaldaemon.com...
 Looks like a good idea.  I've always like how that could be done similarly
 in VB. It should be part of the standard.

 Of coarse you could always invent your own and write it like....

 str4 = left(str1, 5) ~ str2[3..4] ~ right(str3, 6);

You can not. Not without templates, or macros. I would not define a separate "left" function for each array type I could possibly use. No way.
 On a slightly different note.
 Perhaps there could also be a way of creating your own

 for arrays (or any type for that matter).  Perhaps that could be something
 included in Generics when it's implemented. Or perhaps we should just

 to using classes.

The problem is, that you are unable to mimic the behaviour of built-in types (due to lack of operator overload), so you can not make a separate class which seems to be the extension of the built-in array. (see the vector template in c++ STL). I can think of several other operations on arrays, which could happily fit with the member function syntax. Such as insertion. Yes I know you can "emulate" insertion with slicing. The code is ugly, and dangerously redundant. I have a bet that the underlying code is slower that the one which could be implemented for insertion. Now if I, or a general library provider, want to make an array which has insertion as a member function, I need to say goodbye to the [] operator. Too bad.
 Hmmm....

 Or perhaps the property (getters and setters) syntax in D could be
 extended...

 char[] left(char[] in String, int in value) {...}

You mean something like: anyType[] left(anyType[] in Array, int in value) { ... }
 Would be equate to...

     string2 = left(string, 5);
 and ...
     string2 = string.left(5);

That's interesting. It rather seems to me an extension of the function call sytax. A rather promissing extension. That means you can extend any class with member functions of a special kind: - They can only access public members - They are public - They cannot be called based on context. (you allways need to specify the object instance) Appart from the last restriction it is like deriving a class from the base class and giving it the same name. Several problems could be solved elegantly with this extension. Another idea based on this one: I would be happy to see a special access keyword "shallow" for member functions. Such member function could only access public members of the same class. It has to be public of course. It is usefull for similar reasons than the private and protected members. To help modularity. I could provide examples if you need.
 And the setter (if needed)

     void left(char[] in String, int in value) {...}

No. It differs only in return value type.
     string.left(5) = "The first 5 letters of this sentence.";

 Or something along those lines...(I sense problems with what I just

That expression can be evaluated as replacing the first 5 array elements with any number of other array elements; moving the rest of the array if needed. But I don't think that this is really necessary. I would be happy with only read-only properties for this time. Yours, Sandor
Jul 12 2002
parent reply "anderson" <anderson firestar.com.au> writes:
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:agm9pc$1ati$1 digitaldaemon.com...
 "anderson" <anderson firestar.com.au> wrote in message
 news:agga0i$1mop$1 digitaldaemon.com...
 Looks like a good idea.  I've always like how that could be done


 in VB. It should be part of the standard.

 Of coarse you could always invent your own and write it like....

 str4 = left(str1, 5) ~ str2[3..4] ~ right(str3, 6);

You can not. Not without templates, or macros. I would not define a separate "left" function for each array type I could possibly use. No way.

What about void (void * for arrays)? Or is that depreciated for variable use in D? Anyway I'm assumping D will have generics in the future (2.0).
 On a slightly different note.
 Perhaps there could also be a way of creating your own

 for arrays (or any type for that matter).  Perhaps that could be


 included in Generics when it's implemented. Or perhaps we should just

 to using classes.

The problem is, that you are unable to mimic the behaviour of built-in

 (due to lack of operator overload), so you can not make a separate class
 which seems to be the extension of the built-in array. (see the vector
 template in c++ STL).

Parhaps there could be a way to extend types into classes (and template classes) and then use them.
 I can think of several other operations on arrays, which could happily fit
 with the member function syntax. Such as insertion.
 Yes I know you can "emulate" insertion with slicing. The code is ugly, and
 dangerously redundant. I have a bet that the underlying code is slower

 the one which could be implemented for insertion.
 Now if I, or a general library provider, want to make an array which has
 insertion as a member function, I need to say goodbye to the [] operator.
 Too bad.
 Hmmm....

 Or perhaps the property (getters and setters) syntax in D could be
 extended...

 char[] left(char[] in String, int in value) {...}

You mean something like: anyType[] left(anyType[] in Array, int in value) { ... }

anyType[] left(void[] in Array, int in value) { ... } Yeah, but In some cases you'd want to be specific.
 Would be equate to...

     string2 = left(string, 5);
 and ...
     string2 = string.left(5);

That's interesting. It rather seems to me an extension of the function

 sytax. A rather promissing extension.
 That means you can extend any class with member functions of a special

 - They can only access public members
 - They are public
 - They cannot be called based on context. (you allways need to specify the
 object instance)

 Appart from the last restriction it is like deriving a class from the base
 class and giving it the same name. Several problems could be solved
 elegantly with this extension.

 Another idea based on this one: I would be happy to see a special access
 keyword "shallow" for member functions. Such member function could only
 access public members of the same class. It has to be public of course. It
 is usefull for similar reasons than the private and protected members. To
 help modularity. I could provide examples if you need.

No, I get the idea. It seems like a good idea, because many times you have to much class information to deal with. The only disadvantage is that if used improperly, code reuse could be sacificed. It should also apply to member variables, just to make things complete.
 And the setter (if needed)

     void left(char[] in String, int in value) {...}

No. It differs only in return value type.

Which is something I think D should have if you refur to my previous disscussions about using cast() with the return type. Actually, that code wouldn't have worked (no pointer to what we are modifying). I relize that (that's way I said I sense problems). Parhaps... void left(int in value, char[] in String, char[] inout String) {...} Would be more apropriate. But still there are problems because how will the compiler reconise it from a differn't type getter/setter type?
     string.left(5) = "The first 5 letters of this sentence.";

 Or something along those lines...(I sense problems with what I just

That expression can be evaluated as replacing the first 5 array elements with any number of other array elements; moving the rest of the array if needed.

Exactly.
 But I don't think that this is really necessary. I would be happy
 with only read-only properties for this time.

I would also but I do like things to be complete, and read/write seems more complete to me.
 Yours,
 Sandor

Jul 12 2002
next sibling parent "anderson" <anderson firestar.com.au> writes:
 What about void (void * for arrays)? Or is that depreciated for variable

 in D? Anyway I'm assumping D will have generics in the future (2.0).

I relize that void * brings in a list of other problems (such as size determination).
Jul 13 2002
prev sibling parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
"anderson" <anderson firestar.com.au> wrote in message
news:agoc15$17v7$1 digitaldaemon.com...
 The problem is, that you are unable to mimic the behaviour of built-in


 (due to lack of operator overload), so you can not make a separate class
 which seems to be the extension of the built-in array. (see the vector
 template in c++ STL).

Parhaps there could be a way to extend types into classes (and template classes) and then use them.

Maybe if you derive a struct from a basic type, you inherit all the operators that apply to the basic type and can then override them? Perhaps in method syntax (named) form (such as "add" instead of "+") I can think of a few uses for operator overloading where you just want the operators for the basic type without the actual storage for it. And sometimes you want extra operators that the type doesn't ordinarily have. Not to mention possibly operators that *no* builtin types possess. Sean
Jul 13 2002
next sibling parent "anderson" <anderson firestar.com.au> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:agoqpa$23p4$1 digitaldaemon.com...
 "anderson" <anderson firestar.com.au> wrote in message
 news:agoc15$17v7$1 digitaldaemon.com...
 The problem is, that you are unable to mimic the behaviour of built-in


 (due to lack of operator overload), so you can not make a separate



 which seems to be the extension of the built-in array. (see the vector
 template in c++ STL).

Parhaps there could be a way to extend types into classes (and template classes) and then use them.

Maybe if you derive a struct from a basic type, you inherit all the operators that apply to the basic type and can then override them?

 in method syntax (named) form (such as "add" instead of "+")

 I can think of a few uses for operator overloading where you just want the
 operators for the basic type without the actual storage for it.  And
 sometimes you want extra operators that the type doesn't ordinarily have.
 Not to mention possibly operators that *no* builtin types possess.

 Sean

Sounds like a good idea. How would the syntax look? Keep the brain storming comming. --I remember java did it using clases (ie the integer class). I know that it's methods were ineffecient and unclean, but that fact that they implemented it must of ment that there was some use for it.
Jul 13 2002
prev sibling parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:agoqpa$23p4$1 digitaldaemon.com...

 Maybe if you derive a struct from a basic type, you inherit all the
 operators that apply to the basic type and can then override them?

 in method syntax (named) form (such as "add" instead of "+")

 I can think of a few uses for operator overloading where you just want the
 operators for the basic type without the actual storage for it.  And
 sometimes you want extra operators that the type doesn't ordinarily have.
 Not to mention possibly operators that *no* builtin types possess.

 Sean

The best thing to me still seems to be giving Object a few extra methods, such as add(), sub(), mul() and div() and map the operators to calls to these functions. This is already done for == I believe? The standard implementation of these methods in Object would be to just throw an exception, while descendant classes may choose to override this behaviour. The problem is you would also need to have overloaded versions of these methods for the basic types, but that just means Object will have a lot of methods, not a real serious problem. I think the basic types are pretty fixed? For the operator + you would have: class Object { // ..... Object add (Object param); Object add (int param); Object add (extended param); Object add (char param); Object add (complex param); // Ofcourse the ideal form would be with templates <template T> Object add (T param); } So I think this is something for D 2.0 What problems do you see with an approach such as this? Any insights? -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mail
Jul 14 2002
next sibling parent reply "anderson" <anderson firestar.com.au> writes:
 The best thing to me still seems to be giving Object
 a few extra methods, such as add(), sub(), mul()
 and div() and map the operators to calls to these
 functions. This is already done for == I believe?

 The standard implementation of these methods in Object
 would be to just throw an exception, while descendant
 classes may choose to override this behaviour.
 The problem is you would also need to have overloaded
 versions of these methods for the basic types, but
 that just means Object will have a lot of methods, not
 a real serious problem. I think the basic types are
 pretty fixed?

 For the operator + you would have:

 class Object
 {
    // .....
    Object add (Object param);
    Object add (int param);
    Object add (extended param);
    Object add (char param);
    Object add (complex param);

    // Ofcourse the ideal form would be with templates
    <template T>
    Object add (T param);
 }

 So I think this is something for D 2.0
 What problems do you see with an approach such as
 this? Any insights?

Yes, that's pretty simular to C++ but with nicer syntax. We were discussing being able to add "D properties" to standard data types and arrays. so, class Object : int { ... } or as Sean suggested use, struct Object : int { } Also you should add app (append ~) to your list.
 --
 Stijn
 OddesE_XYZ hotmail.com
 http://OddesE.cjb.net
 _________________________________________________
 Remove _XYZ from my address when replying by mail

Jul 14 2002
parent "OddesE" <OddesE_XYZ hotmail.com> writes:
"anderson" <anderson firestar.com.au> wrote in message
news:agtj1g$l6t$1 digitaldaemon.com...

 Also you should add app (append ~) to your list.

Yes, you are right. -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mail
Jul 16 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:ags8db$2eot$1 digitaldaemon.com...
 The best thing to me still seems to be giving Object
 a few extra methods, such as add(), sub(), mul()
 and div() and map the operators to calls to these
 functions. This is already done for == I believe?

This is a pretty good idea. My only objection is that I never liked the C++ approach of being able to override the global operator+ too, producing the confusing combination of: struct A { int operator + (X); }; int operator+ (A, X); Note the inherent asymmetry of this, especially if A::operator+ turns out to be virtual. The STL has some complicated examples of how to get into trouble with this, especially when you throw templates into the mix. A better approach would be to simply disallow overloading the global operators, and say "no" to overloading the syntax: 1 + A; An alternative is for the compiler to rewrite (1+A) as (A+1) and then look for an operator+ overload, but that can lead to trouble for (A+B) where both A and B overload operator+.
Jul 24 2002
next sibling parent reply Pavel Minayev <evilone omen.ru> writes:
On Wed, 24 Jul 2002 18:09:33 -0700 "Walter" <walter digitalmars.com> wrote:

 A better approach would be to simply disallow overloading the global
 operators, and say "no" to overloading the syntax:
 
     1 + A;

On other hand, it might be even better to disallow _member_ operators, and require all operators overloading to be global. Then, you don't have to care about things like virtual operators, overloading etc - it's all naturally done by pointer conversions.
Jul 24 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374624470316435 news.digitalmars.com...
 On Wed, 24 Jul 2002 18:09:33 -0700 "Walter" <walter digitalmars.com>

 A better approach would be to simply disallow overloading the global
 operators, and say "no" to overloading the syntax:

     1 + A;

On other hand, it might be even better to disallow _member_ operators, and require all operators overloading to be global. Then, you don't have to care about things like virtual operators, overloading etc - it's all naturally done by pointer conversions.

Of course, you're right, but unfortunately I screwed up and allowed the cmp operator to be a member <g>.
Aug 01 2002
parent Pavel Minayev <evilone omen.ru> writes:
On Thu, 1 Aug 2002 15:30:13 -0700 "Walter" <walter digitalmars.com> wrote:

 Of course, you're right, but unfortunately I screwed up and allowed the cmp
 operator to be a member <g>.

Then, with introduction of new overloading scheme, the default version of operator(==) and friends would just call cmp(). =)
Aug 02 2002
prev sibling next sibling parent reply Patrick Down <pat codemoon.com> writes:
"Walter" <walter digitalmars.com> wrote in
news:ahnj39$133m$1 digitaldaemon.com:  
 A better approach would be to simply disallow overloading the global
 operators, and say "no" to overloading the syntax:
 
     1 + A;
 
 An alternative is for the compiler to rewrite (1+A) as (A+1) and then
 look for an operator+ overload, but that can lead to trouble for (A+B)
 where both A and B overload operator+.

There are mathmatical systems where A*B != B*A. I'm sort of inclined to agree with Pavel and say that all operators must be defined globally. The only problem would be not being able to acess private members.
Jul 25 2002
next sibling parent reply "anderson" <anderson firestar.com.au> writes:
"Patrick Down" <pat codemoon.com> wrote in message
news:Xns92565926D1F8Cpatcodemooncom 63.105.9.61...
 "Walter" <walter digitalmars.com> wrote in
 news:ahnj39$133m$1 digitaldaemon.com:
 A better approach would be to simply disallow overloading the global
 operators, and say "no" to overloading the syntax:

     1 + A;

 An alternative is for the compiler to rewrite (1+A) as (A+1) and then
 look for an operator+ overload, but that can lead to trouble for (A+B)
 where both A and B overload operator+.

There are mathmatical systems where A*B != B*A. I'm sort of inclined to agree with Pavel and say that all operators must be defined globally. The only problem would be not being able to acess private members.

And protected... You'd end up writting your own add/sub/ect... method anyway. Order is signficatant. Parhaps you could provide 3 versions with special rules? Both (default) - Only usable if the other class doesn't have a Both property to do with this class. (ie this class can't Both to itself.) Left (L) - Only usable if the other class doesn't have a Right property to do with this class. (ie this class can Left to itself) Right (R) - Only usable if the other class doesn't have a Left property to do with this class. There doesn't seem to be an easy solution to this problem. There are probably problems that can still occur with the above.
Jul 25 2002
next sibling parent reply Pavel Minayev <evilone omen.ru> writes:
On Fri, 26 Jul 2002 00:10:16 +0800 "anderson" <anderson firestar.com.au> wrote:

 I'm sort of inclined to agree with Pavel and
 say that all operators must be defined globally.
 The only problem would be not being able to acess
 private members.

And protected... You'd end up writting your own add/sub/ect... method anyway.

Operator overloading is typically used from _within_ the module where classes are defined, so maybe a special rule stating that overloaded operator can access private/protected class members in classes it gets as arguments? Yes, it will be a violation of strict OOP-approach, but at least it'd: 1) work, and 2) be easy to understand.
Jul 25 2002
parent Patrick Down <pat codemoon.com> writes:
Pavel Minayev <evilone omen.ru> wrote in
news:CFN374629860625579 news.digitalmars.com: 

 On Fri, 26 Jul 2002 00:10:16 +0800 "anderson"
 <anderson firestar.com.au> wrote: 
 
 I'm sort of inclined to agree with Pavel and
 say that all operators must be defined globally.
 The only problem would be not being able to acess
 private members.

And protected... You'd end up writting your own add/sub/ect... method anyway.

Operator overloading is typically used from _within_ the module where classes are defined, so maybe a special rule stating that overloaded operator can access private/protected class members in classes it gets as arguments? Yes, it will be a violation of strict OOP-approach, but at least it'd: 1) work, and 2) be easy to understand.

How about static class members? class Foo { static add(Foo a, Foo b) { } static add(Foo a, int b) { } };
Jul 25 2002
prev sibling parent reply Suporte Internet <suporte spica.mps.com.br> writes:
Why not suply diferent methods for handling comutativity and
associativity :

class x : y
{
	override void comute(...) { ... }
	override void associate(...) {...}
	void add(...) { ... }
	void mul(...) {...}
	void div(...) {...}
	void dif(...) {...}
}

anderson <anderson firestar.com.au> wrote:
 
 "Patrick Down" <pat codemoon.com> wrote in message
 news:Xns92565926D1F8Cpatcodemooncom 63.105.9.61...
 "Walter" <walter digitalmars.com> wrote in
 news:ahnj39$133m$1 digitaldaemon.com:
 A better approach would be to simply disallow overloading the global
 operators, and say "no" to overloading the syntax:

     1 + A;

 An alternative is for the compiler to rewrite (1+A) as (A+1) and then
 look for an operator+ overload, but that can lead to trouble for (A+B)
 where both A and B overload operator+.

There are mathmatical systems where A*B != B*A. I'm sort of inclined to agree with Pavel and say that all operators must be defined globally. The only problem would be not being able to acess private members.

And protected... You'd end up writting your own add/sub/ect... method anyway. Order is signficatant. Parhaps you could provide 3 versions with special rules? Both (default) - Only usable if the other class doesn't have a Both property to do with this class. (ie this class can't Both to itself.) Left (L) - Only usable if the other class doesn't have a Right property to do with this class. (ie this class can Left to itself) Right (R) - Only usable if the other class doesn't have a Left property to do with this class.

Jul 25 2002
parent Mark Evans <Mark_member pathlink.com> writes:
Forgive me for joining a conversation I have not followed but I saw some
comments about operators.

Has anyone looked into blitz++?  This is a cool C++ library with special
expressiveness.

Given the chance to define a whole new language better than C++ I should think D
could do at least as well.  Take a peek at it!

Sorry if this comment is not exactly on-topic.

M.
Jul 25 2002
prev sibling parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"Patrick Down" <pat codemoon.com> wrote in message
news:Xns92565926D1F8Cpatcodemooncom 63.105.9.61...
<SNIP>
 There are mathmatical systems where A*B != B*A.

Does this hold for builtin types? What I mean is that I know that for matrix mul this is true, so MatA * MatB != MatB * MatA, but I think that that is not a problem, because this rule only applies to builtin types such as int and double? MatA * 2.0 == 2.0 * MatA isn't it? Do you have an example where this would be a problem? e.g. object * int != int * object or object * double != double * object? Maybe with complex numbers? Mmmm.... -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mail
Jul 25 2002
parent Mark Evans <Mark_member pathlink.com> writes:
For whatever my vote is worth -- as a long time user of mathematics systems like
Mathematica -- I would like commutivity to be user-definable.

Even though Mathematica is a fantastic symbolic solver, it is awful for
noncommutative work, precisely because of built in assumptions about
commutivity.  I would rather the compiler let me tell it what I want for any
given operator.

M.
Jul 25 2002
prev sibling next sibling parent reply "Juan Carlos Arevalo Baeza" <jcab roningames.com> writes:
"Walter" <walter digitalmars.com> wrote in message
news:ahnj39$133m$1 digitaldaemon.com...

 "OddesE" <OddesE_XYZ hotmail.com> wrote in message
 news:ags8db$2eot$1 digitaldaemon.com...
 The best thing to me still seems to be giving Object
 a few extra methods, such as add(), sub(), mul()
 and div() and map the operators to calls to these
 functions. This is already done for == I believe?

This is a pretty good idea. My only objection is that I never liked the

 approach of being able to override the global operator+ too, producing the
 confusing combination of:

 struct A
 {
     int operator + (X);
 };
 int operator+ (A, X);

 Note the inherent asymmetry of this, especially if A::operator+ turns out

 be virtual. The STL has some complicated examples of how to get into

 with this, especially when you throw templates into the mix.

 A better approach would be to simply disallow overloading the global
 operators, and say "no" to overloading the syntax:

     1 + A;

 An alternative is for the compiler to rewrite (1+A) as (A+1) and then look
 for an operator+ overload, but that can lead to trouble for (A+B) where

 A and B overload operator+.

Like anderson said. You can use different versions. I'd use two, the "normal" version and the reverse version: class Vector: object { Vector add(Vector other); // Enough for both commutations Vector mul(double other); // Vector * double Vector rmul(double other); // double * Vector }; class Matrix: object { Matrix add(Matrix other); // Enough for both commutations Matrix mul(double other); // Matrix * double Matrix rmul(double other); // double * Matrix Vector rmul(Vector other); // Vector * Matrix }; You can always easily do the disambiguation in whichever manner is most consistent with D rules. Salutaciones, JCAB
Jul 25 2002
parent "Walter" <walter digitalmars.com> writes:
That is a good idea. I'm sorry I missed it when anderson said it.

"Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
news:ahpjb0$7k7$1 digitaldaemon.com...
  Like anderson said. You can use different versions. I'd use two, the
 "normal" version and the reverse version:

 class Vector: object {
   Vector add(Vector other); // Enough for both commutations
   Vector mul(double other); // Vector * double
   Vector rmul(double other); // double * Vector
 };

 class Matrix: object {
   Matrix add(Matrix other); // Enough for both commutations
   Matrix mul(double other); // Matrix * double
   Matrix rmul(double other); // double * Matrix
   Vector rmul(Vector other); // Vector * Matrix
 };

    You can always easily do the disambiguation in whichever manner is most
 consistent with D rules.

 Salutaciones,
                          JCAB

Aug 01 2002
prev sibling parent reply "Sandor Hojtsy" <hojtsy index.hu> writes:
"Walter" <walter digitalmars.com> wrote in message
news:ahnj39$133m$1 digitaldaemon.com...
 "OddesE" <OddesE_XYZ hotmail.com> wrote in message
 news:ags8db$2eot$1 digitaldaemon.com...
 The best thing to me still seems to be giving Object
 a few extra methods, such as add(), sub(), mul()
 and div() and map the operators to calls to these
 functions. This is already done for == I believe?

This is a pretty good idea.

Gee, Walter, so you are not completely against operator overloading, after all. But what would be the parameters of those methods in Object? I hope not: void add(Object a, Object b) Because "2" is not an Object. So you already need some kind of template here.
 My only objection is that I never liked the C++
 approach of being able to override the global operator+ too, producing the
 confusing combination of:

 struct A
 {
     int operator + (X);
 };
 int operator+ (A, X);

 Note the inherent asymmetry of this, especially if A::operator+ turns out

 be virtual. The STL has some complicated examples of how to get into

 with this, especially when you throw templates into the mix.

 A better approach would be to simply disallow overloading the global
 operators, and say "no" to overloading the syntax:

     1 + A;

Saying "no" seems too restrictive. And counter-intuitive, isn't it? But as told on other threads, with some syntax sugar, you don't need global operator for this.
 An alternative is for the compiler to rewrite (1+A) as (A+1) and then look
 for an operator+ overload, but that can lead to trouble for (A+B) where

 A and B overload operator+.

How would you rewrite 1-A ? Sandor
Jul 30 2002
parent reply Pavel Minayev <evilone omen.ru> writes:
On Tue=2C 30 Jul 2002 11=3A00=3A57 +0200 =22Sandor Hojtsy=22
=3Chojtsy=40index=2Ehu=3E wrote=3A

=3E Gee=2C Walter=2C so you are not completely against operator overloading=2C
after
=3E all=2E
=3E But what would be the parameters of those methods in Object=3F I hope not=3A
=3E void add=28Object a=2C Object b=29
=3E Because =222=22 is not an Object=2E So you already need some kind of
template
=3E here=2E

I guess it'd work like this=3A

=09class Vector
=09{
=09=09=2E=2E=2E
=09=09Vector mul=28Vector v=29 { =2E=2E=2E }=09=09=2F=2F Vector + Vector
=09=09Vector mul=28int n=29 { =2E=2E=2E }=09=09=2F=2F Vector + int
=09}

But then=2C what about int + Vector=3F
I still think static methods with special syntax would be better=3A

=09class Vector
=09{
=09=09=2E=2E=2E
=09=09static operator* =28Vector a=2C Vector b=29 { =2E=2E=2E }
=09=09static operator* =28Vector a=2C int b=29 { =2E=2E=2E }
=09}

Short and clear=2E
 
=3E How would you rewrite 1-A =3F

-=28A-1=29=2C assuming that we can overload unary operators as well=2E
But it might not always work=2E
Jul 30 2002
next sibling parent reply "Sandor Hojtsy" <hojtsy index.hu> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374676619595486 news.digitalmars.com...

 How would you rewrite 1-A ?


-(A-1), assuming that we can overload unary operators as well.
But it might not always work.

Only if unary minus is actually overloaded. Or would you require to overload it for all cases where the binary minus is overloaded? And also restrict binary minus operations to those which satisfy -(A-1) == 1-A ?? For example: You are creating a class to implement a "set" of integers. Set a = new Set, b = new Set; a ~= 1; a ~= 3; a ~= 6; b ~= 3; b ~= 4; Set c = a - b; As defined by the well known set operations, "c" will contain the elements which are present in "a", but not in "b". Now -(a-b) != b-a. Yes, I know you don't need to reorder here, but the example shows that you should not altogether disallow binary minus where -(a-b) != b-a. So you cannot reorder in all cases. How should the compiler now when is it OK to reorder? It brings in more problems, than the few it solves. Conclusion: This reorder idea is Baaad. Yours, Sandor
Jul 30 2002
parent reply Pavel Minayev <evilone omen.ru> writes:
On Tue, 30 Jul 2002 16:52:25 +0200 "Sandor Hojtsy" <hojtsy index.hu> wrote:

 Conclusion: This reorder idea is Baaad.

Agreed. I just wanted to show how it _could_ be done. But I definitely don't like it.
Jul 30 2002
parent "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374678967827778 news.digitalmars.com...
 On Tue, 30 Jul 2002 16:52:25 +0200 "Sandor Hojtsy" <hojtsy index.hu>

 Conclusion: This reorder idea is Baaad.

Agreed. I just wanted to show how it _could_ be done. But I definitely don't like it.

Yes, reordering will not work. Reordering relies on special properties of integers, which don't even apply to floating point operations.
Aug 03 2002
prev sibling next sibling parent "Juan Carlos Arevalo Baeza" <jcab roningames.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374676619595486 news.digitalmars.com...

I guess it'd work like this:

class Vector
{
...
Vector mul(Vector v) { ... } // Vector + Vector
Vector mul(int n) { ... } // Vector + int
}

But then, what about int + Vector?

As I said, a simple and complete solution would be: class Vector { ... Vector mul(Vector v) { ... } // Vector + Vector Vector mul(int n) { ... } // Vector + int Vector reverse_mul(int n) { ... } // int + Vector } Ahem... being verbose ;-) Salutaciones, JCAB
Jul 30 2002
prev sibling next sibling parent "OddesE" <OddesE_XYZ hotmail.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374676619595486 news.digitalmars.com...
On Tue, 30 Jul 2002 11:00:57 +0200 "Sandor Hojtsy" <hojtsy index.hu> wrote:
 I still think static methods with special syntax would be better:

 class Vector
 {
 ...
 static operator* (Vector a, Vector b) { ... }
 static operator* (Vector a, int b) { ... }
 }

 Short and clear.

Sounds good, you have my vote on this! I don't know about operator* as a name though..., this would forbid calling the function directly wouldn't it? I can imagine some operator-overloading haters not being happy with that...If you would call it mul you could also call it directly, some people might prefer that... -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mail
Jul 31 2002
prev sibling next sibling parent reply "anderson" <anderson firestar.com.au> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374676619595486 news.digitalmars.com...
On Tue, 30 Jul 2002 11:00:57 +0200 "Sandor Hojtsy" <hojtsy index.hu> wrote:

 class Vector
 {
 ...
 static operator* (Vector a, Vector b) { ... }
 static operator* (Vector a, int b) { ... }
 }

 Short and clear.

I think * would be confused with pointers.
 How would you rewrite 1-A ?


Juan offered a better solution I think because you get proper access to the object properties and it's less special-case.
Jul 31 2002
parent reply Jonathan Andrew <jon ece.arizona.edu> writes:
anderson wrote:
 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:CFN374676619595486 news.digitalmars.com...
 On Tue, 30 Jul 2002 11:00:57 +0200 "Sandor Hojtsy" <hojtsy index.hu> wrote:
 
 
class Vector
{
...
static operator* (Vector a, Vector b) { ... }
static operator* (Vector a, int b) { ... }
}

Short and clear.

I think * would be confused with pointers.
How would you rewrite 1-A ?


Juan offered a better solution I think because you get proper access to the object properties and it's less special-case.

You would have to have different 'keywords' for each symbol, i.e, for vectors you might want to overload * for cross product and constant multiples, but have . for dot product also, which one would mul be? I suppose you could have a dot keyword also, but I like the idea of being able to explicitly specify which symbol to use. Maybe something like class Vector { static operator(*) cross(VectorA, VectorB); static operator(*) mul(VectorA, int); static operator(.) dot(VectorA, VectorB); .... etc. } This way, those who don't like operator overloading could still call the functions by name, i.e. cross(), dot() etc. and you could specify which symbol to use also. Just an idea, -Jon
Jul 31 2002
next sibling parent reply "anderson" <anderson firestar.com.au> writes:
"Jonathan Andrew" <jon ece.arizona.edu> wrote in message
news:3D4862F1.3070709 ece.arizona.edu...
 anderson wrote:
 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:CFN374676619595486 news.digitalmars.com...
 On Tue, 30 Jul 2002 11:00:57 +0200 "Sandor Hojtsy" <hojtsy index.hu>


class Vector
{
...
static operator* (Vector a, Vector b) { ... }
static operator* (Vector a, int b) { ... }
}

Short and clear.

I think * would be confused with pointers.
How would you rewrite 1-A ?


Juan offered a better solution I think because you get proper access to


 object properties and it's less special-case.

You would have to have different 'keywords' for each symbol, i.e, for vectors you might want to overload * for cross product and constant multiples, but have . for dot product also, which one would mul be? I suppose you could have a dot keyword also, but I like the idea of being able to explicitly specify which symbol to use. Maybe something like class Vector { static operator(*) cross(VectorA, VectorB); static operator(*) mul(VectorA, int); static operator(.) dot(VectorA, VectorB); .... etc. } This way, those who don't like operator overloading could still call the functions by name, i.e. cross(), dot() etc. and you could specify which symbol to use also. Just an idea, -Jon

No, I agree with you. I was thinking (to stop it looking pointerish) ... class Vector { operator<*>(VectorA, VectorB); operator<->(VectorA, int); operator<.>(VectorA, VectorB); .... etc. } Or another symbol because () makes it look like a weird function (but is better then without). because it's having to remember the name for each symbol simply means more learning. The more things you have in the language the more you need to remember. However if the user could specify any name they wished... Anyhow in your example how would the complier determine the differce between a cross and a mul? I think that would be a bug. Also I think that it shouldn't be static. I like Juan's approach here better. My approch is closest to Juan (uses differn't syntax). class VectorA { leftOperator<*>(VectorB); leftOperator<->(int); leftOperator<.>(VectorB); rightOperator<.>(VectorB); } or even simpler class VectorA { left<*>(VectorB); left<->(int); left<.>(VectorB); right<.>(VectorB); } and users who what to specify... class VectorA { left<*> mul(VectorB); left<-> whatever(int); left<.> dot(VectorB); right<.> dot(VectorB); } This way you don't have to special case access to class member properties. If you give programs to much power, some are likly to abuse it.
Jul 31 2002
next sibling parent reply Jonathan Andrew <jon ece.arizona.edu> writes:
 
 No, I agree with you. I was thinking (to stop it looking pointerish) ...
 
  class Vector
  {
        operator<*>(VectorA, VectorB);
        operator<->(VectorA, int);
        operator<.>(VectorA, VectorB);
        .... etc.
  }
 Or another symbol because () makes it look like a weird function (but is
 better then without).

True, <> would be a good choice.
 because it's having to remember the name for each symbol simply means more
 learning. The more things you have in the language the more you need to
 remember. However if the user could specify any name they wished... Anyhow
 in your example how would the complier determine the differce between a
 cross and a mul? I think that would be a bug.

It would determine it from the operators, if you had cross and mul that both accepted two vectors, it should err. In my case mul was a constant multiplier.
 Also I think that it shouldn't be static. I like Juan's approach here
 better.

Having static operators available (though not necessary) would be convenient for a lot of cases, like a math class.
 My approch is closest to Juan (uses differn't syntax).
 
  class VectorA
  {
        leftOperator<*>(VectorB);
        leftOperator<->(int);
        leftOperator<.>(VectorB);
        rightOperator<.>(VectorB);
  }
 
 or even simpler
 
  class VectorA
  {
        left<*>(VectorB);
        left<->(int);
        left<.>(VectorB);
        right<.>(VectorB);
  }
 
 and users who what to specify...
 
  class VectorA
  {
        left<*> mul(VectorB);
        left<-> whatever(int);
        left<.> dot(VectorB);
        right<.> dot(VectorB);
  }
 
 This way you don't have to special case access to class member properties.
 If you give programs to much power, some are likly to abuse it.
 
 

Hmm, I dunno, that is more concise, but it seems a little harder to understand.
Jul 31 2002
next sibling parent "anderson" <anderson firestar.com.au> writes:
"Jonathan Andrew" <jon ece.arizona.edu> wrote in message
news:3D48D3BE.404 ece.arizona.edu...
 No, I agree with you. I was thinking (to stop it looking pointerish) ...

  class Vector
  {
        operator<*>(VectorA, VectorB);
        operator<->(VectorA, int);
        operator<.>(VectorA, VectorB);
        .... etc.
  }
 Or another symbol because () makes it look like a weird function (but is
 better then without).

True, <> would be a good choice.
 because it's having to remember the name for each symbol simply means


 learning. The more things you have in the language the more you need to
 remember. However if the user could specify any name they wished...


 in your example how would the complier determine the differce between a
 cross and a mul? I think that would be a bug.

It would determine it from the operators, if you had cross and mul that both accepted two vectors, it should err. In my case mul was a constant multiplier.
 Also I think that it shouldn't be static. I like Juan's approach here
 better.

Having static operators available (though not necessary) would be convenient for a lot of cases, like a math class.
 My approch is closest to Juan (uses differn't syntax).

  class VectorA
  {
        leftOperator<*>(VectorB);
        leftOperator<->(int);
        leftOperator<.>(VectorB);
        rightOperator<.>(VectorB);
  }

 or even simpler

  class VectorA
  {
        left<*>(VectorB);
        left<->(int);
        left<.>(VectorB);
        right<.>(VectorB);
  }

 and users who what to specify...

  class VectorA
  {
        left<*> mul(VectorB);
        left<-> whatever(int);
        left<.> dot(VectorB);
        right<.> dot(VectorB);
  }

 This way you don't have to special case access to class member


 If you give programs to much power, some are likly to abuse it.

Hmm, I dunno, that is more concise, but it seems a little harder to understand.

I really don't care that much. Whatever is writeable, readable, doesn't cause specail cases, easy to learn and effecient. Acually when I first used C++ (a few years ago now) I tried to make an operator like this... class VectorA { * (VectorB); - (int); . (VectorB); } ...but of course there are problems with that such as the right/left rules.
Aug 01 2002
prev sibling parent reply "Martin M. Pedersen" <mmp www.moeller-pedersen.dk> writes:
Hi,

"Jonathan Andrew" <jon ece.arizona.edu> wrote in message
news:3D48D3BE.404 ece.arizona.edu...
        operator<.>(VectorA, VectorB);
        .... etc.


Not really, considering the operators "<", ">", "<<", ">>", etc. "operator<<>" would be recognized by the lexer as the three tokens "operator", "<<", and ">", thereby introducing the need for extra spacing as in "operator< < >" ("<>" is a token recognized by the lexer too). Its the same problem as with templates in C++ - let us learn from it. Regards, Martin M. Pedersen
Aug 01 2002
next sibling parent Jonathan Andrew <jon ece.arizona.edu> writes:
"Martin M. Pedersen" wrote:

 Hi,

 "Jonathan Andrew" <jon ece.arizona.edu> wrote in message
 news:3D48D3BE.404 ece.arizona.edu...
        operator<.>(VectorA, VectorB);
        .... etc.


Not really, considering the operators "<", ">", "<<", ">>", etc. "operator<<>" would be recognized by the lexer as the three tokens "operator", "<<", and ">", thereby introducing the need for extra spacing as in "operator< < >" ("<>" is a token recognized by the lexer too). Its the same problem as with templates in C++ - let us learn from it. Regards, Martin M. Pedersen

Hmm, fair enough, I guess we need to invent a keyboard with some new brackets =) If anything though, I think this whole thread has shown me that built-in vector support in the language would be greatly appreciated!
Aug 01 2002
prev sibling parent reply Pavel Minayev <evilone omen.ru> writes:
On Thu=2C 1 Aug 2002 17=3A29=3A48 +0100 =22Martin M=2E Pedersen=22 
=3Cmmp=40www=2Emoeller-pedersen=2Edk=3E wrote=3A

=3E Not really=2C considering the operators =22=3C=22=2C =22=3E=22=2C
=22=3C=3C=22=2C =22=3E=3E=22=2C etc=2E
=3E =22operator=3C=3C=3E=22 would be recognized by the lexer as the three tokens
=3E =22operator=22=2C =22=3C=3C=22=2C and =22=3E=22=2C thereby introducing the
need for extra spacing as
=3E in =22operator=3C =3C =3E=22 =28=22=3C=3E=22 is a token recognized by the
lexer too=29=2E Its the
=3E same problem as with templates in C++ - let us learn from it=2E

I think round braces are the best choice=2E When grouped properly=2C they
look just alright=3A

=09vector operator=28+=29 =28vector a=2C vector b=29
=09{
=09=09=2E=2E=2E
=09}
Aug 01 2002
parent reply "anderson" <anderson firestar.com.au> writes:
Just stay with the brackets then. As I said, is didn't think <> was a good
option but all other brackets are in uses with C++ so I guess it's the only
option. At least it's better then without.

"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374700137667593 news.digitalmars.com...
On Thu, 1 Aug 2002 17:29:48 +0100 "Martin M. Pedersen"
<mmp www.moeller-pedersen.dk> wrote:

 Not really, considering the operators "<", ">", "<<", ">>", etc.
 "operator<<>" would be recognized by the lexer as the three tokens
 "operator", "<<", and ">", thereby introducing the need for extra spacing

 in "operator< < >" ("<>" is a token recognized by the lexer too). Its the
 same problem as with templates in C++ - let us learn from it.

I think round braces are the best choice. When grouped properly, they look just alright: vector operator(+) (vector a, vector b) { ... }
Aug 01 2002
parent reply Patrick Down <pat codemoon.com> writes:
"anderson" <anderson firestar.com.au> wrote in
news:aickhl$peh$1 digitaldaemon.com: 

 
 vector operator(+) (vector a, vector b)
 {
 ...
 }

vector operator"+"(vector a, vector b) { }
Aug 01 2002
parent reply "anderson" <anderson firestar.com.au> writes:
"Patrick Down" <pat codemoon.com> wrote in message
news:Xns925DCD940507patcodemooncom 63.105.9.61...
 "anderson" <anderson firestar.com.au> wrote in
 news:aickhl$peh$1 digitaldaemon.com:

 vector operator(+) (vector a, vector b)
 {
 ...
 }

vector operator"+"(vector a, vector b) { }

That's an idea. <babble> - Parhaps you can get some ideas from this Come to think of it I remember a language (I thing VB) that put variables with spaces in square brackets like: [go to the shops] = [go to the shops] + 1 If course you couldn't use square brackets in D, but perhaps the same symbol could be used for spaces in words as well. perhaps vector _+_ (vector a, vector b) { } and for functions with spaces int _function with space_ () {} but "_" may not stand out enough so I'd recommend something else. Personally I'd really like it if the operator keyword could be left out all-together but I don't think that would get though the consensus. //Perhaps vector a+b (vector a, vector b) { } and for reverse vector b+a (vector b, vector a) { } or (but then things get difficult to determine order) vector (vector b)+(vector a) { } But I'd still like it to be part of the class object as well. It probably should be a constructor come to think of it. //Is there any need for reversing here? this (vector b) + (vector a) { } //int + vector this (int b) + (vector a) { } //vector + int this (vector b) + (int a) { } //That is simular to a global method but it's more part of the object //However, if you have two classes with the same inputs, how do you determine which one to use // I'd suggest explictily telling it like when there is a problem (hopefully rare - and in any case casting could be used): int a; vector b; vector C; vectorB new, new2; new = a + b; //Uses vectorB method new2 = a + vector(+) c; //Uses vector's method or new = a + b; //Uses vectorB method new2 = a + vector.+ c; //Uses vector's method //But then you'll still have precedence problems (for example if you want to work from backwards) //Parhaps syntax from EBNF (Extended Backus-Naur form) - Walter should be familiar with this, //could be used in some way. For anyone else, it's a way of discribing syntax like the complier does. //Such as operator precedence and associativity. I don't have any ideas there (yet).
Aug 01 2002
parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
If operator overloading makes it into D, one of the cool things in C++ is
the Spirit parser generator ( spirit.sourceforge.net ) which implements
quasi-EBNF in C++ using operator overloading.  So to avoid some of the
problems they had, it'd be nice if there were support for postfix * and
postfix +.

But there's already enough ambiguity with * to cause your head to spin.

Sean

"anderson" <anderson firestar.com.au> wrote in message
news:aid6lp$1cuc$1 digitaldaemon.com...
 //But then you'll still have precedence problems (for example if you want

 work from backwards)
 //Parhaps syntax from EBNF (Extended Backus-Naur form) - Walter should be
 familiar with this,
 //could be used in some way. For anyone else, it's a way of discribing
 syntax like the complier does.
 //Such as operator precedence and associativity. I don't have any ideas
 there (yet).

Aug 03 2002
parent reply "anderson" <anderson firestar.com.au> writes:
I was thing parhaps precedence could be done with a number.

this a+b 5(vector a, vector b); //Precidence level 5
this b+a 5(vector a, vector b); //Precidence level 5 (reverse)
this z*x 4(vector z, vector x); //Precedence level 4

//Of course there would be a default precedence, so the numbers should only
be used by the experts

"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:aig81s$21jv$1 digitaldaemon.com...
 If operator overloading makes it into D, one of the cool things in C++ is
 the Spirit parser generator ( spirit.sourceforge.net ) which implements
 quasi-EBNF in C++ using operator overloading.  So to avoid some of the
 problems they had, it'd be nice if there were support for postfix * and
 postfix +.

 But there's already enough ambiguity with * to cause your head to spin.

 Sean

That also. Except, parhaps that could not be done on the operator level parhaps something like = prefix(+ X Y) = postfix(X Y -)
 "anderson" <anderson firestar.com.au> wrote in message
 news:aid6lp$1cuc$1 digitaldaemon.com...
 //But then you'll still have precedence problems (for example if you


 to
 work from backwards)
 //Parhaps syntax from EBNF (Extended Backus-Naur form) - Walter should


 familiar with this,
 //could be used in some way. For anyone else, it's a way of discribing
 syntax like the complier does.
 //Such as operator precedence and associativity. I don't have any ideas
 there (yet).


Aug 03 2002
next sibling parent reply Pavel Minayev <evilone omen.ru> writes:
On Sat, 3 Aug 2002 20:49:30 +0800 "anderson" <anderson firestar.com.au> wrote:

 I was thing parhaps precedence could be done with a number.
 
 this a+b 5(vector a, vector b); //Precidence level 5
 this b+a 5(vector a, vector b); //Precidence level 5 (reverse)
 this z*x 4(vector z, vector x); //Precedence level 4
 
 //Of course there would be a default precedence, so the numbers should only
 be used by the experts

I think that user-defined operator precedence is just too complex, and mostly unused feature. Does it really worth Walter's time to spend to implement it?
Aug 03 2002
next sibling parent "anderson" <anderson firestar.com.au> writes:
Your probably right.

"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374717849229282 news.digitalmars.com...
 On Sat, 3 Aug 2002 20:49:30 +0800 "anderson" <anderson firestar.com.au>

 I was thing parhaps precedence could be done with a number.

 this a+b 5(vector a, vector b); //Precidence level 5
 this b+a 5(vector a, vector b); //Precidence level 5 (reverse)
 this z*x 4(vector z, vector x); //Precedence level 4

 //Of course there would be a default precedence, so the numbers should


 be used by the experts

I think that user-defined operator precedence is just too complex, and mostly unused feature. Does it really worth Walter's time to spend to implement it?

Aug 03 2002
prev sibling parent "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374717849229282 news.digitalmars.com...
 I think that user-defined operator precedence is just too complex,
 and mostly unused feature. Does it really worth Walter's time to
 spend to implement it?

I think it's not a good idea to implement. For one thing, it breaks the idea of separating the syntactical from the semantic analysis.
Aug 08 2002
prev sibling parent reply "anderson" <anderson firestar.com.au> writes:
"anderson" <anderson firestar.com.au> wrote in message
news:aigj6n$2d5d$1 digitaldaemon.com...
I was thinking precedence could be done with a number parhaps.
 this a+b 5(vector a, vector b); //Precidence level 5
 this b+a 5(vector a, vector b); //Precidence level 5 (reverse)
 this z*x 4(vector z, vector x); //Precedence level 4

 //Of course there would be a default precedence, so the numbers should

 be used by the experts

Aug 03 2002
parent user domain.invalid writes:
I think the precedence for the operator, which way it runs (left to 
right, or vice versa), and whether it is a postfix, prefix, or not 
should be left to the default settings. If it's a left -> right 
operator, the operator function for the object on the left is called. It 
could be defined like this:

class myClass {
	int w = 0, x = 5;
	operator(+, int i) {return w + x + i;} // the operator is passed as the 
first argument to operator function
	operator(+, myClass i) {return w + x + i.w + i.x } // the call to 
operator function is chosen by which operator is used and w/ which data type
}
Aug 23 2002
prev sibling parent reply Juarez Rudsatz <juarez nowhere.com> writes:
"anderson" <anderson firestar.com.au> wrote in news:aia87q$2m8d$1
 digitaldaemon.com:

 No, I agree with you. I was thinking (to stop it looking pointerish) ...
 
  class Vector
  {
        operator<*>(VectorA, VectorB);
        operator<->(VectorA, int);
        operator<.>(VectorA, VectorB);
        .... etc.
  }
 Or another symbol because () makes it look like a weird function (but is
 better then without).

Why not use the keyword and type already available in language : Class Vector { void add (int A) {} // V + 1 int add () {} // 1 + A }
Aug 01 2002
parent reply Jonathan Andrew <jon ece.arizona.edu> writes:
Juarez Rudsatz wrote:

 "anderson" <anderson firestar.com.au> wrote in news:aia87q$2m8d$1
  digitaldaemon.com:

 No, I agree with you. I was thinking (to stop it looking pointerish) ...

  class Vector
  {
        operator<*>(VectorA, VectorB);
        operator<->(VectorA, int);
        operator<.>(VectorA, VectorB);
        .... etc.
  }
 Or another symbol because () makes it look like a weird function (but is
 better then without).

Why not use the keyword and type already available in language : Class Vector { void add (int A) {} // V + 1 int add () {} // 1 + A }

This keeps you from being able to define new symbols to use, and sometimes there are cases where it would be nice to use symbols that don't necessarily represent adding, so forth. For example, if you had some kind of class for a signal function, and you wanted * to represent convolution, you wouldn't want to use a function called mul() to represent that operation, even though it uses the same symbol. (on a keyboard at least)
Aug 01 2002
next sibling parent Juarez Rudsatz <juarez nowhere.com> writes:
Jonathan Andrew <jon ece.arizona.edu> escreveu em news:3D497E7A.F479D5B3
 ece.arizona.edu:

 This keeps you from being able to define new symbols to use, and
 sometimes there are cases where it would be nice to use symbols
 that don't necessarily represent adding, so forth.
 For example, if you had some kind of class for a signal function,
 and you wanted * to represent convolution, you wouldn't want to
 use a function called mul() to represent that operation, even though
 it uses the same symbol. (on a keyboard at least)
 

I have read another post which speak about having not the operation but the symbol used:
 Maybe something like
 class Vector
 {
       static operator(*) cross(VectorA, VectorB);
       static operator(*) mul(VectorA, int);
       static operator(.) dot(VectorA, VectorB);
       .... etc.
 }
 

In this example, the compiler can, without many problems, associate the symbol "+" with the identifier "cross". There are no need of specify it in all operator declaration. And another post which specify a serious problem:
 A better approach would be to simply disallow overloading the global
 operators, and say "no" to overloading the syntax:
 
     1 + A;
 
 An alternative is for the compiler to rewrite (1+A) as (A+1) and then
 look for an operator+ overload, but that can lead to trouble for (A+B)
 where both A and B overload operator+.
 

But this have a problem
 There are mathmatical systems where A+B != B+A.

In this example, maybe could solve by making the signal operator ordinary procedures and funcions (void and <type>). Rewriting all of this we could have: class someType { override void cross(int i) { // this will take care of expressions like // A + 1 } override int cross() { // this will take care of expressions like // 1 + A } } And all of this could be writed in two forms: A := A + 1; or A.cross(1 + A.cross()); -- dmd -JR
Aug 01 2002
prev sibling parent "anderson" <anderson firestar.com.au> writes:
This is a slightly different question then this line, but still in the same
subject matter. In C++ I always had trouble accessing the hidden datatypes
of the other member. If I didn't have direct access to some variable I'd
have to write a function member so that I could access it (or even worse
make the variable public). While is ok in some cases, in others it breaks
the structure of the data abstraction, allowing access to members that
shouldn't be even scene.

Perhaps using static (with full access to both members privates) is the
solution to this, but I recon there may be some better idea. Parhaps, and
I'm by no way clear on the details, could add some type of privlage system
on member functions so that we can specify which functions have access to
which members (or something, I'm not clear on the idea here). Parhaps I
could be simular to java packages. Parhaps a class could belong to seveal
prilage groups. Or parhaps theres some other better idea. I would really
like the solution to this to be non-special case. Parhaps D already has
something.

"Jonathan Andrew" <jon ece.arizona.edu> wrote in message
news:3D497E7A.F479D5B3 ece.arizona.edu...
 Juarez Rudsatz wrote:

 "anderson" <anderson firestar.com.au> wrote in news:aia87q$2m8d$1
  digitaldaemon.com:

 No, I agree with you. I was thinking (to stop it looking pointerish)



  class Vector
  {
        operator<*>(VectorA, VectorB);
        operator<->(VectorA, int);
        operator<.>(VectorA, VectorB);
        .... etc.
  }
 Or another symbol because () makes it look like a weird function (but



 better then without).

Why not use the keyword and type already available in language : Class Vector { void add (int A) {} // V + 1 int add () {} // 1 + A }

This keeps you from being able to define new symbols to use, and sometimes there are cases where it would be nice to use symbols that don't necessarily represent adding, so forth. For example, if you had some kind of class for a signal function, and you wanted * to represent convolution, you wouldn't want to use a function called mul() to represent that operation, even though it uses the same symbol. (on a keyboard at least)

Aug 01 2002
prev sibling parent C.R.Chafer <blackmarlin nospam.asean-mail.com> writes:
Jonathan Andrew wrote:

 
 Maybe something like
 class Vector
 {
       static operator(*) cross(VectorA, VectorB);
       static operator(*) mul(VectorA, int);
       static operator(.) dot(VectorA, VectorB);
       .... etc.
 }
 
 This way, those who don't like operator overloading could
 still call the functions by name, i.e. cross(), dot() etc.
 and you could specify which symbol to use also.
 Just an idea,
   -Jon

I like the idea - especially as it is similar to the method I use in my language (oomic) .. however in the latter case the syntax is different so you would get: function subtract Vector as ( a - b ) ;; a Vector , b Vector { ... } function negate Vector as ( - a ) ;; a Vector { ... } The main advantage here is that the equation parser can be used to parse the operator overloading specifier. Here of course there is no need to specify left / right / binary association (though post fix operators are not allowed in the current version). Maybe this idea could be adapted for D? C 2002/8/1
Aug 01 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
Yes, but then virtual calls won't work for them. Sigh.

"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374676619595486 news.digitalmars.com...
class Vector
{
...
static operator* (Vector a, Vector b) { ... }
static operator* (Vector a, int b) { ... }
}
Short and clear.
Aug 03 2002
parent reply Pavel Minayev <evilone omen.ru> writes:
On Sat=2C 3 Aug 2002 14=3A49=3A29 -0700 =22Walter=22
=3Cwalter=40digitalmars=2Ecom=3E wrote=3A

=3E Yes=2C but then virtual calls won't work for them=2E Sigh=2E

If one REALLY needs a virtual operator =28so far I didn't=29=2C he could
just wrap a function call into it=3A

=09class Foo
=09{
=09=09Foo op=5Fmul=28Foo b=29 { =2E=2E=2E }=09=2F=2F this one is virtual!
=09=09Foo operator=28*=29 =28Foo a=2C Foo b=29 { return a=2Eop=5Fmul=28b=29=3B }
=09}

Overloaded operators are mostly used for vectors=2C matrices=2C and
alike=2C where perfomance is typically more important=2E There is
no sence of having a virtual operator+ for vectors=2E Could anybody
show an example where virtual operators are really needed=3F
Aug 03 2002
next sibling parent "anderson" <anderson firestar.com.au> writes:
But why not simply have the function call in the first place as the
operator?

"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374721052143982 news.digitalmars.com...
On Sat, 3 Aug 2002 14:49:29 -0700 "Walter" <walter digitalmars.com> wrote:

 Yes, but then virtual calls won't work for them. Sigh.

If one REALLY needs a virtual operator (so far I didn't), he could just wrap a function call into it: class Foo { Foo op_mul(Foo b) { ... } // this one is virtual! Foo operator(*) (Foo a, Foo b) { return a.op_mul(b); } } Overloaded operators are mostly used for vectors, matrices, and alike, where perfomance is typically more important. There is no sence of having a virtual operator+ for vectors. Could anybody show an example where virtual operators are really needed?
Aug 03 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:CFN374721052143982 news.digitalmars.com...
Overloaded operators are mostly used for vectors, matrices, and
alike, where perfomance is typically more important. There is
no sence of having a virtual operator+ for vectors. Could anybody
show an example where virtual operators are really needed?

The compare operator when building, say, a generic array sorter.
Aug 04 2002
next sibling parent Pavel Minayev <evilone omen.ru> writes:
On Sun, 4 Aug 2002 08:15:32 -0700 "Walter" <walter digitalmars.com> wrote:

 The compare operator when building, say, a generic array sorter.

It can always be implemented as a virtual cmp() function. Besided, you won't need it to be virtual if that array sorter would be templated.
Aug 04 2002
prev sibling parent reply "anderson" <anderson firestar.com.au> writes:
Just wondering what the argument against virtual static members is? I've
never read anything against them in books. I'm sure there's a good reason
they weren't implemented in C++. So what it the reasoning against virtual
static members?

Thanks
Aug 04 2002
next sibling parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
Because it doesn't make sense to call a static method through an object
reference?  But how else do you get the compiler to "figure out" which
version of the function to call?  Seems you either want a static function
(non-virtual) or a virtual member function.

How would you use one if you had the capability?

Sean

"anderson" <anderson firestar.com.au> wrote in message
news:aikj9d$2bh1$1 digitaldaemon.com...
 Just wondering what the argument against virtual static members is? I've
 never read anything against them in books. I'm sure there's a good reason
 they weren't implemented in C++. So what it the reasoning against virtual
 static members?

 Thanks

Aug 05 2002
parent "anderson" <anderson firestar.com.au> writes:
Class ClassA
{
    virtual static int Var;

    virtual static void Something();
}

Class ClassB : ClassA
{
    virtual static void Something();
}

And you wouldn't use a just an object reference, you'd use the class name.

ClassA.Something();
ClassB.Something();

ClassA.Var = 11; //Class a's Var has 11
ClassB.Var = 10; //Class b's Var has 10 and class A's var still has 11

Although using a object reference may make sense sometimes.

Basicly to deal with properties and methods that are one per class not per
class and all child classes as well.  It treats a class as the group of
objects on one level.

There are work-arounds, but why use them when you could use the proper
thing.

I'm sure there's gota be a better reason then that. Parhaps it's to hard to
implement in the complier, parhaps it's ineffecient, parhaps it should be
defined using a parallel object sturcture.

Here's a few other newsgroup links that portray the same opinion (I couldn't
find any good reasons against so that's why I'm asking).

http://dbforums.com/archive/89/2001/06/1/65121
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&th=ca8b
a27e7944e9ab&rnum=1
http://groups.google.com/groups?q=%22static+virtual+methods%22+%22C%2B%2B%22
&hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=3904%40lulea.trab.se&rnum=5


"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:ailbl9$18sd$1 digitaldaemon.com...
 Because it doesn't make sense to call a static method through an object
 reference?  But how else do you get the compiler to "figure out" which
 version of the function to call?  Seems you either want a static function
 (non-virtual) or a virtual member function.

 How would you use one if you had the capability?

 Sean

 "anderson" <anderson firestar.com.au> wrote in message
 news:aikj9d$2bh1$1 digitaldaemon.com...
 Just wondering what the argument against virtual static members is? I've
 never read anything against them in books. I'm sure there's a good


 they weren't implemented in C++. So what it the reasoning against


 static members?

 Thanks


Aug 05 2002
prev sibling parent reply "Juan Carlos Arevalo Baeza" <jcab roningames.com> writes:
"anderson" <anderson firestar.com.au> wrote in message
news:aikj9d$2bh1$1 digitaldaemon.com...

 Just wondering what the argument against virtual static members is? I've
 never read anything against them in books. I'm sure there's a good reason
 they weren't implemented in C++. So what it the reasoning against virtual
 static members?

What you mean is having a global function that can dynamically dispatch according to an object's real type. That can definitely be done (see Mozart in SourceForge), but it is a bit complicated. In C++ and D, dynamic dispatch is designed for virtual function tables, although that particular implementation is not necessarily used. This was done by requiring every class to know, beforehand, all the functions it'll dynamically dispatch to. The "object.function()" syntax can be seen as just syntactic sugar, really. Allowing arbitrary virtual functions to be added outside of the class would require a different method. The upside of this is that, if such a method is implemented, multiple dynamic dispatch comes naturally (that's why Mozart supports it). It would be a worthwhile addition to the language, except for all the complication (which is quite a bit). Salutaciones, JCAB
Aug 13 2002
parent "anderson" <anderson firestar.com.au> writes:
Thanks.

"Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
news:ajcd0u$2g3a$1 digitaldaemon.com...
 "anderson" <anderson firestar.com.au> wrote in message
 news:aikj9d$2bh1$1 digitaldaemon.com...

 Just wondering what the argument against virtual static members is? I've
 never read anything against them in books. I'm sure there's a good


 they weren't implemented in C++. So what it the reasoning against


 static members?

What you mean is having a global function that can dynamically dispatch according to an object's real type. That can definitely be done (see

 in SourceForge), but it is a bit complicated. In C++ and D, dynamic

 is designed for virtual function tables, although that particular
 implementation is not necessarily used. This was done by requiring every
 class to know, beforehand, all the functions it'll dynamically dispatch

 The "object.function()" syntax can be seen as just syntactic sugar,

 Allowing arbitrary virtual functions to be added outside of the class

 require a different method. The upside of this is that, if such a method

 implemented, multiple dynamic dispatch comes naturally (that's why Mozart
 supports it).

    It would be a worthwhile addition to the language, except for all the
 complication (which is quite a bit).

 Salutaciones,
                          JCAB

Aug 13 2002