D - Array operator overloading
- Walter (7/7) Sep 08 2003 I'm thinking that the following operator overload functions will cover t...
- QUS (6/11) Sep 08 2003 Why not the whole "operator"?
- Helmut Leitner (12/28) Sep 08 2003 "Add" seems wrong to me, because no element is added in the usual sense.
- QUS (5/29) Sep 08 2003 an
- Matthew Wilson (17/24) Sep 08 2003 Well, I'm not fond of having my ass indexed!
- Riccardo De Agostini (7/8) Sep 08 2003 Maybe opIndexAsLValue, although maybe too verbose, is a better choice. A...
- Sean L. Palmer (31/38) Sep 08 2003 "op"
- Ilya Minkov (19/27) Sep 08 2003 Seems to be all there. But you have to know it better. :)
- Daniel Yokomiso (31/38) Sep 08 2003 "op"
- Walter (14/47) Sep 08 2003 the
- Matthew Wilson (13/67) Sep 09 2003 Sean's ideas sound quite good. I'm not sure I saw different _l and _r in
- Sean L. Palmer (18/23) Sep 09 2003 You could certainly have a different one for get than for set. It might...
- Mike Wynn (7/20) Sep 09 2003 yes, dump the comma operator, for those that want it add "eval" if you
- Ilya Minkov (8/14) Sep 09 2003 With a recursive descend parser it shouldn't matter that something
- Matthew Wilson (1/12) Sep 09 2003 Even better!
- Philippe Mori (20/36) Sep 09 2003 or
- Sean L. Palmer (18/34) Sep 10 2003 -operator
- Walter (3/6) Sep 09 2003 Unfortunately, that doesn't work for things like reverse divide.
- Mike Wynn (14/25) Sep 09 2003 what about "operator rev_divide" etc
- Walter (3/4) Sep 09 2003 They're just like other functions, i.e. virtual.
- Sean L. Palmer (8/15) Sep 10 2003 This is why you make two versions, one with A on left and B on right, an...
- Riccardo De Agostini (11/18) Sep 10 2003 How about:
- Walter (4/22) Sep 11 2003 That'll work, but it just doesn't look like much of an improvement :-(
- Riccardo De Agostini (33/35) Sep 12 2003 I certainly didn't even try to think how it would be implemented in the
- Daniel Yokomiso (28/63) Sep 09 2003 [snip]
- Walter (11/20) Sep 09 2003 Yes, and you're right.
- Daniel Yokomiso (29/43) Sep 11 2003 ----- Original Message -----
- Patrick Down (9/22) Sep 11 2003 I like this approach for the indexing operator. I don't have a big
- Walter (3/7) Sep 11 2003 That might be a good compromise.
- Matthew Wilson (3/6) Sep 12 2003 I've revised my antipathy to ambiguousness upwards, and now will be unha...
I'm thinking that the following operator overload functions will cover the territory. Have I missed anything? x = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x); foo[a .. b] => foo.opSlice(a, b); And yes, I think the other operator overloads should be renamed with an "op" prefix.
Sep 08 2003
x = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x); foo[a .. b] => foo.opSlice(a, b); And yes, I think the other operator overloads should be renamed with an"op"prefix.Why not the whole "operator"? operatorIndex operatorAdd operatorMulass etc?
Sep 08 2003
QUS wrote:"Add" seems wrong to me, because no element is added in the usual sense. "Mulass" seems wrong to me, because it is not a "multiple assignment", but a single assignment of an array part to an array reference. In my language built with reusable "words": opIndRetElement opIndSetElement opIndRangeRetSlice (but I would not expect it to be adopted) -- Helmut Leitner leitner hls.via.at Graz, Austria www.hls-software.comx = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x); foo[a .. b] => foo.opSlice(a, b); And yes, I think the other operator overloads should be renamed with an"op"prefix.Why not the whole "operator"? operatorIndex operatorAdd operatorMulass
Sep 08 2003
"Helmut Leitner" <leitner hls.via.at> wrote in message news:3F5C45DE.3AC22592 hls.via.at...QUS wrote:anx = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x); foo[a .. b] => foo.opSlice(a, b); And yes, I think the other operator overloads should be renamed withNaaaah! What I meant is just to unfold op to operator. The examples I gave had nothing to do with array overloading :-)"op""Add" seems wrong to me, because no element is added in the usual sense. "Mulass" seems wrong to me, because it is not a "multiple assignment", but a single assignment of an array part to an array reference. In my language built with reusable "words": opIndRetElement opIndSetElement opIndRangeRetSliceprefix.Why not the whole "operator"? operatorIndex operatorAdd operatorMulass
Sep 08 2003
Well, I'm not fond of having my ass indexed! I think a prefix of op is not good enough (i.e. not sufficiently unique). I would prefer OP_slice, or op_slice As for the two index operators, I think they should be called op_index_r and op_index_l (for rvalue and lvalue) But actually I think this may not be the whole solution. We might want to return a proxy object for both types, as one does in C++. In that case, we'd want op_index_l op_index_r op_index op_index would only be called where one or other of the l/r variants was not provided. "Walter" <walter digitalmars.com> wrote in message news:bjhefn$2qdb$1 digitaldaemon.com...I'm thinking that the following operator overload functions will cover the territory. Have I missed anything? x = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x); foo[a .. b] => foo.opSlice(a, b); And yes, I think the other operator overloads should be renamed with an"op"prefix.
Sep 08 2003
"Walter" <walter digitalmars.com> ha scritto nel messaggio news:bjhefn$2qdb$1 digitaldaemon.com...foo[y] = x; => foo.opIndexAss(y, x);Maybe opIndexAsLValue, although maybe too verbose, is a better choice. At least it leaves both hands free for typing. ;-) BTW, I find "op" as a prefix a little too concise; I'd vote for "operator", or "op_" as suggested by Matthew. Ric
Sep 08 2003
"Walter" <walter digitalmars.com> wrote in message news:bjhefn$2qdb$1 digitaldaemon.com...I'm thinking that the following operator overload functions will cover the territory. Have I missed anything? x = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x); foo[a .. b] => foo.opSlice(a, b); And yes, I think the other operator overloads should be renamed with an"op"prefix.I'm ok with the short op prefix as you suggest. I do not see how one could pull off multidimensional arrays without proxy objects. I think we should be able to declare indexing functions that take more than one argument, and the compiler would give us syntax sugar like so: template (T : numeric, int cols, int rows) struct matrix { private T array[rows][cols]; public T opIndex(int col, int row) { return array[row][col]; } public void opIndexSet(T val, int col, int row) { array[row][col] = val; } public instance matrix(T, colrange.end-colrange.begin, rowrange.end-rowrange.begin).matrix opSlice(range(int) colrange, range(int) rowrange) { return array[rowrange.begin..rowrange.end][colrange.begin..colrange.end]; } } instance matrix(float, 4, 4).matrix mymatrix; mymatrix[3][2] = 1.0f; // calls opIndexSet(1.0f,2,3) float x = mymatrix[3][2]; // calls opIndex(2,3) instance matrix(float, 2, 2).matrix submatrix = matrix[1..3][0..2]; // calls opSlice(0..2,1..3) And one more thing... we need to be able to override the array .length property. Hopefully you can override a predefined property with a user-defined one. Sean
Sep 08 2003
Walter wrote:I'm thinking that the following operator overload functions will cover the territory. Have I missed anything?Seems to be all there. But you have to know it better. :) Ah, yes, the multi-dimensional ones would be good, since you provide different names anyway this shouldn't be a problem, right?x = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x);x = foo[y,z]; => x = foo.opIndex(y,z); foo[y,z] = x; => foo.opIndexAss(y,z,x);foo[a .. b] => foo.opSlice(a, b);foo[a,b .. c,d] => foo.opSlice(a,b,c,d); Could this possibly work at all??? Is it supposed to return a new array or a proxy object at will?And yes, I think the other operator overloads should be renamed with an "op" prefix.Seems to be a good idea to me... But what about that _r postfix? You get opDiv_r -- which seems to be inconsistent within itself? How about op_div_r, and so on for operator naming? Or do you prefer opDivR? Is there any chance to keep naming for array access consistent with properties? In Delphi, an object can contain a number of array acessors which would work like properties. Then you can pick up one of them and set a default attribute for it, then acessing an object as an array would use exactly these acessors... In D this may better simply be the name of the array property. -eye
Sep 08 2003
"Walter" <walter digitalmars.com> escreveu na mensagem news:bjhefn$2qdb$1 digitaldaemon.com...I'm thinking that the following operator overload functions will cover the territory. Have I missed anything? x = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x); foo[a .. b] => foo.opSlice(a, b); And yes, I think the other operator overloads should be renamed with an"op"prefix.Why not: x = foo[y]; => x = foo.get(y); foo[y] = x; => foo.set(y, x); foo[a .. b] => foo.slice(a, b); The other operator names are already nice (i.e. "add" instead of "opAdd"). BTW will array operations be overloaded? Today the spec says: a[] = b[] + 3; => for (int i = 0; i < a.length; i++) { a[i] = b[i] + 3; } But if I have a collection, will it work? I'm saying that because we'll need to define some array-like data-structures (e.g. matrices, vector spaces) and would be nice to have array operations (like Blitz++ has tensor notation). Perhaps an "indices" operation could be used: a[] = b[] + 3; foreach (??? i; a.indices()) {a[i] = b[i] + 3; } Also it would be nice if I could define more than one index, so a matrix could be written: x = foo[i, j]; => x = foo.get(i, j); foo[i, j] = x; => foo.set(i, j, x); foo[0 .. a, 0 .. b] => foo.slice(0 .. a, 0 .. b); Best regards, Daniel Yokomiso. "Sometimes I think the surest sign that intelligent life exists elsewhere in the universe is that none of it has tried to contact us." - Bill Watterson --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.514 / Virus Database: 312 - Release Date: 28/8/2003
Sep 08 2003
"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message news:bjj5bg$2ah0$1 digitaldaemon.com..."Walter" <walter digitalmars.com> escreveu na mensagem news:bjhefn$2qdb$1 digitaldaemon.com...theI'm thinking that the following operator overload functions will coverHmm. I kinda was thinking "add" was just a little too generic, that it might need something to say it's a magic function to the compiler. Python sets off the operator overloading with a __ prefix and postfix (which I find unattractive, but it does stand out).territory. Have I missed anything? x = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x); foo[a .. b] => foo.opSlice(a, b); And yes, I think the other operator overloads should be renamed with an"op"prefix.Why not: x = foo[y]; => x = foo.get(y); foo[y] = x; => foo.set(y, x); foo[a .. b] => foo.slice(a, b); The other operator names are already nice (i.e. "add" instead of "opAdd"). BTW will array operations be overloaded? Today the spec says:a[] = b[] + 3; => for (int i = 0; i < a.length; i++) { a[i] = b[i] + 3; } But if I have a collection, will it work? I'm saying that because we'llneedto define some array-like data-structures (e.g. matrices, vector spaces)andwould be nice to have array operations (like Blitz++ has tensor notation). Perhaps an "indices" operation could be used: a[] = b[] + 3; foreach (??? i; a.indices()) {a[i] = b[i] + 3; }Since [] is a slice operation, I was thinking that this could be handled with the slice operator overload (having it return a different object, with its own operator overloads).Also it would be nice if I could define more than one index, so a matrix could be written: x = foo[i, j]; => x = foo.get(i, j); foo[i, j] = x; => foo.set(i, j, x); foo[0 .. a, 0 .. b] => foo.slice(0 .. a, 0 .. b);Sean has some ideas along this line: x = foo[x][y]; => x = foo.get(x,y);
Sep 08 2003
Sean's ideas sound quite good. I'm not sure I saw different _l and _r in there, though. One thing I *definitely* think is important, is to avoid generic names such as add(). At minimum it should be op_add(), and I'd prefer __add__(), or even __op_add__(). "Walter" <walter digitalmars.com> wrote in message news:bjjd6g$2kvk$1 digitaldaemon.com..."Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message news:bjj5bg$2ah0$1 digitaldaemon.com...an"Walter" <walter digitalmars.com> escreveu na mensagem news:bjhefn$2qdb$1 digitaldaemon.com...theI'm thinking that the following operator overload functions will coverterritory. Have I missed anything? x = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x); foo[a .. b] => foo.opSlice(a, b); And yes, I think the other operator overloads should be renamed with"opAdd")."op"prefix.Why not: x = foo[y]; => x = foo.get(y); foo[y] = x; => foo.set(y, x); foo[a .. b] => foo.slice(a, b); The other operator names are already nice (i.e. "add" instead ofmightBTW will array operations be overloaded? Today the spec says:Hmm. I kinda was thinking "add" was just a little too generic, that itneed something to say it's a magic function to the compiler. Python setsoffthe operator overloading with a __ prefix and postfix (which I find unattractive, but it does stand out).notation).a[] = b[] + 3; => for (int i = 0; i < a.length; i++) { a[i] = b[i] + 3; } But if I have a collection, will it work? I'm saying that because we'llneedto define some array-like data-structures (e.g. matrices, vector spaces)andwould be nice to have array operations (like Blitz++ has tensorwithPerhaps an "indices" operation could be used: a[] = b[] + 3; foreach (??? i; a.indices()) {a[i] = b[i] + 3; }Since [] is a slice operation, I was thinking that this could be handled with the slice operator overload (having it return a different object,its own operator overloads).Also it would be nice if I could define more than one index, so a matrix could be written: x = foo[i, j]; => x = foo.get(i, j); foo[i, j] = x; => foo.set(i, j, x); foo[0 .. a, 0 .. b] => foo.slice(0 .. a, 0 .. b);Sean has some ideas along this line: x = foo[x][y]; => x = foo.get(x,y);
Sep 09 2003
"Matthew Wilson" <matthew stlsoft.org> wrote in message news:bjk32t$l31$1 digitaldaemon.com...Sean's ideas sound quite good. I'm not sure I saw different _l and _r in there, though.You could certainly have a different one for get than for set. It might be nice to support [x,y] notation as well, especially for true rectangular arrays, not arrays of arrays. But that would conflict with the comma operator. There are already conflicts with the comma operator pretty much everywhere comma is accepted (i.e. parameter lists) so this is not the end of the world.One thing I *definitely* think is important, is to avoid generic namessuchas add(). At minimum it should be op_add(), and I'd prefer __add__(), or even __op_add__().I prefer the "real" names: operator + operator [] etc. There is no possibility of confusion, and you're saying exactly what you want. You want an operator overload for +=, then by god overload operator +=, not "addass". This would leave *all* those names available for the user member namespace. Sean
Sep 09 2003
Sean L. Palmer wrote:"Matthew Wilson" <matthew stlsoft.org> wrote in message news:bjk32t$l31$1 digitaldaemon.com...yes, dump the comma operator, for those that want it add "eval" if you realy need a set of expressions as an expression. x = eval( a = x, b=c, c ); same as current `x = (a=x), (b=c), c; ` then comma is just list separator in all cases. eval is kind of extern(pascal order, caller clean up) T eval( ..., T rv );Sean's ideas sound quite good. I'm not sure I saw different _l and _r in there, though.You could certainly have a different one for get than for set. It might be nice to support [x,y] notation as well, especially for true rectangular arrays, not arrays of arrays. But that would conflict with the comma operator. There are already conflicts with the comma operator pretty much everywhere comma is accepted (i.e. parameter lists) so this is not the end of the world.
Sep 09 2003
Mike Wynn wrote:yes, dump the comma operator, for those that want it add "eval" if you realy need a set of expressions as an expression. x = eval( a = x, b=c, c ); same as current `x = (a=x), (b=c), c; ` then comma is just list separator in all cases. eval is kind of extern(pascal order, caller clean up) T eval( ..., T rv );With a recursive descend parser it shouldn't matter that something conflicts with a comma operator, as long as you don't need to expect comma operator in the same context. However, i think dunping the operator and providing a named variant for it is a good idea! However, as it cannot be overloaded, i can hardly figure out any use for it at all... -eye
Sep 09 2003
Even better!One thing I *definitely* think is important, is to avoid generic namessuchas add(). At minimum it should be op_add(), and I'd prefer __add__(), or even __op_add__().I prefer the "real" names: operator + operator [] etc. There is no possibility of confusion, and you're saying exactly what you want. You want an operator overload for +=, then by god overload operator +=, not "addass".
Sep 09 2003
"Matthew Wilson" <matthew stlsoft.org> a écrit dans le message de news:bjldl8$2j4j$1 digitaldaemon.com...orOne thing I *definitely* think is important, is to avoid generic namessuchas add(). At minimum it should be op_add(), and I'd prefer __add__(),operatoreven __op_add__().I prefer the "real" names: operator + operator [] etc. There is no possibility of confusion, and you're saying exactly what you want. You want an operator overload for +=, then by god overloadI also prefer "real" name... as in C++ but I think that for postfix++ and similar it should be a "postfix" modifier... and for case where we want to make the distinction between l-value and r-value, we should also uses a modifier. I would like that operator[] support multiple arguments as a function and yes we might uses the suggestion eval for an expression that presently uses comman operator and ban it. but if something like eval is added, I would also like that this would be possible: if (int a = f(), a == 25) { } where we could do 1 (ore more) declaration and expression before doing the test... we might uses eval and/or some other keyword presently, in C++ the trick to declare the variable inside an expression essentially only works when we test against 0...+=, not "addass".Even better!
Sep 09 2003
-operator +operator ++operator --operator operator++ operator-- oper+ator oper-ator oper*ator oper/ator oper,ator // I don't mind operator comma as long as you use it to build a list or sequence operator[] operator[][] Harharhar! Sean "Philippe Mori" <philippe_mori hotmail.com> wrote in message news:bjlhf8$2oi4$1 digitaldaemon.com...I also prefer "real" name... as in C++ but I think that for postfix++ and similar it should be a "postfix" modifier... and for case where we want to make the distinction between l-value and r-value, we should also uses a modifier. I would like that operator[] support multiple arguments as a function and yes we might uses the suggestion eval for an expression that presently uses comman operator and ban it. but if something like eval is added, I would also like that this would be possible: if (int a = f(), a == 25) { } where we could do 1 (ore more) declaration and expression before doing the test... we might uses eval and/or some other keyword presently, in C++ the trick to declare the variable inside an expression essentially only works when we test against 0...
Sep 10 2003
"Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:bjkuks$1spu$1 digitaldaemon.com...I prefer the "real" names: operator + operator []Unfortunately, that doesn't work for things like reverse divide.
Sep 09 2003
Walter wrote:"Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:bjkuks$1spu$1 digitaldaemon.com...what about "operator rev_divide" etc class Foo { this() { } Foo operator rev_divide ( Foo f ) { .. } } although I'd rather see binary ops as static T operator op (T a, T b ) so there would be no need for sub/reverse_sub and unary ops as T operator op ( [optional params] ) {..} // [] is a unary op. where "op" is add, sub, etc are operators `virtual` or not ?I prefer the "real" names: operator + operator []Unfortunately, that doesn't work for things like reverse divide.
Sep 09 2003
"Mike Wynn" <mike l8night.co.uk> wrote in message news:bjljc1$2rdb$1 digitaldaemon.com...are operators `virtual` or not ?They're just like other functions, i.e. virtual.
Sep 09 2003
This is why you make two versions, one with A on left and B on right, and one with B on left and A on right. I think you meant reverse subtract? This is only a PITA if the operators are constrained to be member functions. Then you gotta define one parm as "this". Sean "Walter" <walter digitalmars.com> wrote in message news:bjlhbd$2odl$1 digitaldaemon.com..."Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:bjkuks$1spu$1 digitaldaemon.com...I prefer the "real" names: operator + operator []Unfortunately, that doesn't work for things like reverse divide.
Sep 10 2003
"Walter" <walter digitalmars.com> ha scritto nel messaggio news:bjlhbd$2odl$1 digitaldaemon.com..."Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:bjkuks$1spu$1 digitaldaemon.com...How about: operator ++ operator postfix ++ || postfix operator ++ || operator ++ postfix operator - operator reverse - || reverse operator - || operator - reverse operator / operator reverse / || reverse operator / || operator / reverse Did I (as almost usual ;-) ) overlook something? RicI prefer the "real" names: operator + operator []Unfortunately, that doesn't work for things like reverse divide.
Sep 10 2003
"Riccardo De Agostini" <riccardo.de.agostini email.it> wrote in message news:bjmsus$1kmm$1 digitaldaemon.com..."Walter" <walter digitalmars.com> ha scritto nel messaggio news:bjlhbd$2odl$1 digitaldaemon.com...That'll work, but it just doesn't look like much of an improvement :-( Anyhow, I'll think about it some more."Sean L. Palmer" <palmer.sean verizon.net> wrote in message news:bjkuks$1spu$1 digitaldaemon.com...How about: operator ++ operator postfix ++ || postfix operator ++ || operator ++ postfix operator - operator reverse - || reverse operator - || operator - reverse operator / operator reverse / || reverse operator / || operator / reverse Did I (as almost usual ;-) ) overlook something?I prefer the "real" names: operator + operator []Unfortunately, that doesn't work for things like reverse divide.
Sep 11 2003
"Walter" <walter digitalmars.com> ha scritto nel messaggio news:bjqhdm$ja4$3 digitaldaemon.com...That'll work, but it just doesn't look like much of an improvement :-( Anyhow, I'll think about it some more.I certainly didn't even try to think how it would be implemented in the compiler... or you can be sure I'd have overlooked at least 80% of relevant issues, due to total inexperience in the field. But, from my perspective as a _user_ of compilers, this seems, more or less, the way to go (note that I've have little second thoughts with respect to my previous post): 1) the "operator" keyword makes code clearer at the first glance. This is maybe the only place where, IMHO, C++ looks better than D. To be truthful, I should also mention templates, but that's another story (and another thread). 2) Prefix and postfix ++ and -- need not be distinguished, _if_ in the postfix case you call the op-function immediately after evaluation of the subexpression containing the operator. So: if (++b > 42) would be the same as "b.operator ++(); if (b > 42)", while if (b++ > 42) would be the same as "bool temp = (b > 42); b.operator ++(); if (temp)" Again, I don't know if and how much this is practical for you as the compiler's author, but I see no use for two separate ++ operators, other than letting people hurt themselves... :) 3) For non-commutative binary operators, I see two possible ways: either a "reverse" attribute, with the same meaning as the "_r" suffix in current op-funcs, or not having them as members, so they take two parameters whose order is obviously specified in the declaration. 4) Following the same line of thinking, I'd suggest a "lvalue" attribute for the assignable index operator: "operator lvalue []" as opposed to "operator []" which does not (necessarily) return a lvalue. 5) a[3][5] and a[3, 5] are different beasts, I see no need for compiler intervention here. Hope I didn't forget anything this time. :) Ric
Sep 12 2003
"Walter" <walter digitalmars.com> escreveu na mensagem news:bjjd6g$2kvk$1 digitaldaemon.com..."Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message news:bjj5bg$2ah0$1 digitaldaemon.com...[snip]"opAdd").The other operator names are already nice (i.e. "add" instead ofmightBTW will array operations be overloaded? Today the spec says:Hmm. I kinda was thinking "add" was just a little too generic, that itneed something to say it's a magic function to the compiler. Python setsoffthe operator overloading with a __ prefix and postfix (which I find unattractive, but it does stand out).So will you change "eq" and "cmp" too? If we're going to change them, it's better to change them all.notation).a[] = b[] + 3; => for (int i = 0; i < a.length; i++) { a[i] = b[i] + 3; } But if I have a collection, will it work? I'm saying that because we'llneedto define some array-like data-structures (e.g. matrices, vector spaces)andwould be nice to have array operations (like Blitz++ has tensorwithPerhaps an "indices" operation could be used: a[] = b[] + 3; foreach (??? i; a.indices()) {a[i] = b[i] + 3; }Since [] is a slice operation, I was thinking that this could be handled with the slice operator overload (having it return a different object,its own operator overloads).If it's the way it would be nice to create a stride function too: a[1,3,5,7] = 0; // zeroes only the first four odd positions. Strides are nice to certain kinds of operations. Returning an intermediate object wouldn't bloat the code? The advantage of Blitz++ is that you don't have intermediate objects automagically appearing everywhere.Won't this mean "foo.get(x).get(y)"? How will the compiler deal with vectors of vector: "vec[x][y]" will be "vec.get(x,y)" or "vec.get(x).get(y)". Also doesn't it make "(foo[x])[y]" an unexpected error? Best regards, Daniel Yokomiso. "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." - Buckminster Fuller --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.514 / Virus Database: 312 - Release Date: 28/8/2003Also it would be nice if I could define more than one index, so a matrix could be written: x = foo[i, j]; => x = foo.get(i, j); foo[i, j] = x; => foo.set(i, j, x); foo[0 .. a, 0 .. b] => foo.slice(0 .. a, 0 .. b);Sean has some ideas along this line: x = foo[x][y]; => x = foo.get(x,y);
Sep 09 2003
"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message news:bjlmcg$2vf1$1 digitaldaemon.com...So will you change "eq" and "cmp" too? If we're going to change them, it's better to change them all.Yes, and you're right.Strides are nice to certain kinds of operations. Returning an intermediate object wouldn't bloat the code?I don't know yet. Have to try it and see.vectorsSean has some ideas along this line: x = foo[x][y]; => x = foo.get(x,y);Won't this mean "foo.get(x).get(y)"? How will the compiler deal withof vector: "vec[x][y]" will be "vec.get(x,y)" or "vec.get(x).get(y)". Also doesn't it make "(foo[x])[y]" an unexpected error?I was thinking that it could be disambiguated by looking for the existence of: get(int i, int j); vs: get(int i); It would take the longest one it found.
Sep 09 2003
----- Original Message ----- From: "Walter" <walter digitalmars.com> Newsgroups: D Sent: Wednesday, September 10, 2003 3:30 AM Subject: Re: Array operator overloading"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message news:bjlmcg$2vf1$1 digitaldaemon.com...[snip]AlsovectorsSean has some ideas along this line: x = foo[x][y]; => x = foo.get(x,y);Won't this mean "foo.get(x).get(y)"? How will the compiler deal withof vector: "vec[x][y]" will be "vec.get(x,y)" or "vec.get(x).get(y)".Hmmm, this kind of ad hoc parsing wasn't one of the things you were trying to get rid of? If we have "foo[x][y]" I'll probably want to write "bar = foo[x]; baz = bar[y];", but in this case it'll be an error, because "[]" isn't an operator, while "[][]" is. I prefer "foo[x,y]" because it's more concise and unambiguous. BTW I think it's an error to mix the syntax of true multi-dimensional arrays with ragged arrays, we should have true multi-dimensional arrays as a language feature and a ragged array is just a one-dimensional array of arrays: int[] foo; // one-dimensional array of ints int[,] bar; // bi-dimensional array of ints int[][] baz; // one-dimensional array of one-dimensional arrays of ints int[,,][,,,,][] qux; // guess what ;) If we make the syntax clearer will be easier for everyone to use it and the semantics will be clearer (probably the code will be more amenable to optimization). Best regards, Daniel Yokomiso. "If at first you succeed try not to look astonished." --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.514 / Virus Database: 312 - Release Date: 28/8/2003doesn't it make "(foo[x])[y]" an unexpected error?I was thinking that it could be disambiguated by looking for the existence of: get(int i, int j); vs: get(int i); It would take the longest one it found.
Sep 11 2003
"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message news:bjpj65$2b1u$1 digitaldaemon.com...Yes. I don't like it either.It would take the longest one it found.Hmmm, this kind of ad hoc parsing wasn't one of the things you were trying to get rid of?If we have "foo[x][y]" I'll probably want to write "bar = foo[x]; baz = bar[y];", but in this case it'll be an error, because "[]" isn't an operator, while "[][]" is. I prefer "foo[x,y]" because it's more concise and unambiguous. BTW I think it's an error to mix the syntax oftruemulti-dimensional arrays with ragged arrays, we should have true multi-dimensional arrays as a language feature and a ragged array is justaone-dimensional array of arrays: int[] foo; // one-dimensional array of ints int[,] bar; // bi-dimensional array of ints int[][] baz; // one-dimensional array of one-dimensional arrays of ints int[,,][,,,,][] qux; // guess what ;) If we make the syntax clearer will be easier for everyone to use itandthe semantics will be clearer (probably the code will be more amenable to optimization).I guess I'm just so used to the C version of things. I don't know what the right answer is, I'll think about it some more.
Sep 11 2003
Walter wrote:"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message news:bjpj65$2b1u$1 digitaldaemon.com...much as I like the idea of multi-dim arrays being passable, I can forsee someone wanting to pass an N dim array int func( int[,*] f ) { if f.dimensions = 1 .... etc } I think if nothing more this is another reason that growable array should be a templated class, the only think D offers is "block" which can be sliced same syntax as now just no ~=/~ operator on T[] func( T[] f ) { ... same as now arrays are passed with their length. } however with the operator overloading each [] is a call to operator_index foo[a][b] => foo.operator_index(a).operator_index(b) foo[a,b] => foo.operator_index(a,b) foo[a,b][c,d] => foo.operator_index(a,b).operator_index(b,c) either disallow range or pass as a Range object foo[a] => calls foo::operator_index( a.type ) foo[a..b] => calls foo::operator_index( Range ) or calls foo.operator_index( foo.operator_create_range(a, b) ); index then called with the return type from create_range which might be anything. foo[a..b][d] => foo.operator_index( new range(a,b) ).operator_index(d) ranges seem to me to be leading up the c++ path, where although you can overload x,y,z the performance penalty grows with the ease programing/flexability. I think most uses of range are covered by just allowing one use foo[a..b] => operator_slice( int a, int b ) I'm happy to have class My2Obj { int[] operator_index( int a ) { .... } } My2Obj foo; foo[a][b] => foo.operator_index(a).operator_index(b) which is foo.operator_index(a)[b] template array( T ) { class Ar2D { T[] ar; this( int xw, int yw ) { ar = new T[xw*yw]; sw = xw; } int[] operator_index( int a ) { return ar[(a*sw)..(a*sw+sw)] } int operator_index( int a, b ) { return ar[a+(b*sw)] } } alias instance array(int).Ar2D myblock; myBlock foo = new myBlock( xm, ym ); foo[y][x] now equiv to foo[x,y] you can do foo[y] and it behaves like bar = new int[xm][ym]; only bar should be a true array of arrays. that goes for int[4][5] b; should create array of arrays not a single block just a bit of syntactic sugar. what about "put" ? we still need a put to do a hashtable (I like the syntax of assoc arrays, but think they should be classes not primatives) template array( T, M ) { class Hashtable { class Entry { M key; T val; Entry next; } Entry[] ar; this() { } T operator_index( M a ) { return find_in_chain( ar[a.hashcode%ar.length], a ); } }Yes. I don't like it either.It would take the longest one it found.Hmmm, this kind of ad hoc parsing wasn't one of the things you were trying to get rid of?If we have "foo[x][y]" I'll probably want to write "bar = foo[x]; baz = bar[y];", but in this case it'll be an error, because "[]" isn't an operator, while "[][]" is. I prefer "foo[x,y]" because it's more concise and unambiguous. BTW I think it's an error to mix the syntax oftruemulti-dimensional arrays with ragged arrays, we should have true multi-dimensional arrays as a language feature and a ragged array is justaone-dimensional array of arrays: int[] foo; // one-dimensional array of ints int[,] bar; // bi-dimensional array of ints int[][] baz; // one-dimensional array of one-dimensional arrays of ints int[,,][,,,,][] qux; // guess what ;) If we make the syntax clearer will be easier for everyone to use itandthe semantics will be clearer (probably the code will be more amenable to optimization).I guess I'm just so used to the C version of things. I don't know what the right answer is, I'll think about it some more.
Sep 11 2003
Hi, I don't want to disturb you, guys. But I am working a lot in Matlab and it has some nice features for arrays (I think they are the best): -arrays are multidimensional and are indexed as a[2,4,5] (example to select an element); -syntax like a[:,3] will select all the third column of the matrix a; -a[:] will concatenate all the columns of a into 1 column vector; -a*b is standard matrix multiplication while a.*b is multiplying element by element; -the same stands for a^2 and a.^2; -a[4:end] will select the elements from 4 to the end of the vector (no matter how long); -and more... Only to give you an ideea. Felix PS Yes, Matlab is an interpreter, but all the code can be compiled in C. (eh, almost, no objects available for that). In article <bjr184$196c$1 digitaldaemon.com>, Mike Wynn says...Walter wrote:"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message news:bjpj65$2b1u$1 digitaldaemon.com...much as I like the idea of multi-dim arrays being passable, I can forsee someone wanting to pass an N dim array int func( int[,*] f ) { if f.dimensions = 1 .... etc } I think if nothing more this is another reason that growable array should be a templated class, the only think D offers is "block" which can be sliced same syntax as now just no ~=/~ operator on T[] func( T[] f ) { ... same as now arrays are passed with their length. } however with the operator overloading each [] is a call to operator_index foo[a][b] => foo.operator_index(a).operator_index(b) foo[a,b] => foo.operator_index(a,b) foo[a,b][c,d] => foo.operator_index(a,b).operator_index(b,c) either disallow range or pass as a Range object foo[a] => calls foo::operator_index( a.type ) foo[a..b] => calls foo::operator_index( Range ) or calls foo.operator_index( foo.operator_create_range(a, b) ); index then called with the return type from create_range which might be anything. foo[a..b][d] => foo.operator_index( new range(a,b) ).operator_index(d) ranges seem to me to be leading up the c++ path, where although you can overload x,y,z the performance penalty grows with the ease programing/flexability. I think most uses of range are covered by just allowing one use foo[a..b] => operator_slice( int a, int b ) I'm happy to have class My2Obj { int[] operator_index( int a ) { .... } } My2Obj foo; foo[a][b] => foo.operator_index(a).operator_index(b) which is foo.operator_index(a)[b] template array( T ) { class Ar2D { T[] ar; this( int xw, int yw ) { ar = new T[xw*yw]; sw = xw; } int[] operator_index( int a ) { return ar[(a*sw)..(a*sw+sw)] } int operator_index( int a, b ) { return ar[a+(b*sw)] } } alias instance array(int).Ar2D myblock; myBlock foo = new myBlock( xm, ym ); foo[y][x] now equiv to foo[x,y] you can do foo[y] and it behaves like bar = new int[xm][ym]; only bar should be a true array of arrays. that goes for int[4][5] b; should create array of arrays not a single block just a bit of syntactic sugar. what about "put" ? we still need a put to do a hashtable (I like the syntax of assoc arrays, but think they should be classes not primatives) template array( T, M ) { class Hashtable { class Entry { M key; T val; Entry next; } Entry[] ar; this() { } T operator_index( M a ) { return find_in_chain( ar[a.hashcode%ar.length], a ); } }Yes. I don't like it either.It would take the longest one it found.Hmmm, this kind of ad hoc parsing wasn't one of the things you were trying to get rid of?If we have "foo[x][y]" I'll probably want to write "bar = foo[x]; baz = bar[y];", but in this case it'll be an error, because "[]" isn't an operator, while "[][]" is. I prefer "foo[x,y]" because it's more concise and unambiguous. BTW I think it's an error to mix the syntax oftruemulti-dimensional arrays with ragged arrays, we should have true multi-dimensional arrays as a language feature and a ragged array is justaone-dimensional array of arrays: int[] foo; // one-dimensional array of ints int[,] bar; // bi-dimensional array of ints int[][] baz; // one-dimensional array of one-dimensional arrays of ints int[,,][,,,,][] qux; // guess what ;) If we make the syntax clearer will be easier for everyone to use itandthe semantics will be clearer (probably the code will be more amenable to optimization).I guess I'm just so used to the C version of things. I don't know what the right answer is, I'll think about it some more.
Sep 11 2003
"Walter" <walter digitalmars.com> wrote in news:bjhefn$2qdb$1 digitaldaemon.com:I'm thinking that the following operator overload functions will cover the territory. Have I missed anything? x = foo[y]; => x = foo.opIndex(y); foo[y] = x; => foo.opIndexAss(y, x); foo[a .. b] => foo.opSlice(a, b); And yes, I think the other operator overloads should be renamed with an "op" prefix.I like this approach for the indexing operator. I don't have a big opinion on the exact function names but I'm in the op_add, op_mul, op_whatever camp. I would like to have multidimensional indexing and slicing too. I prefer the array[x,y] syntax. I don't think that you need to support it as a basic feature of D arrays but it would be nice to define classes that would support it.
Sep 11 2003
"Patrick Down" <pat codemoon.com> wrote in message news:Xns93F3E63E057FBpatcodemooncom 63.105.9.61...I would like to have multidimensional indexing and slicing too. I prefer the array[x,y] syntax. I don't think that you need to support it as a basic feature of D arrays but it would be nice to define classes that would support it.That might be a good compromise.
Sep 11 2003
I like this approach for the indexing operator. I don't have a big opinion on the exact function names but I'm in the op_add, op_mul, op_whatever camp.I've revised my antipathy to ambiguousness upwards, and now will be unhappy with anything less than the Python-esque __op_add__, __op_index_l__, etc. I'm not holding my breath ... ;(
Sep 12 2003