www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 3474] New: PATCH: Implement opDollar for struct and class indexing operations

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3474

           Summary: PATCH: Implement opDollar for struct and class
                    indexing operations
           Product: D
           Version: 2.036
          Platform: Other
        OS/Version: All
            Status: NEW
          Keywords: patch
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: clugdbug yahoo.com.au


--- Comment #0 from Don <clugdbug yahoo.com.au> 2009-11-05 07:33:37 PST ---
Created an attachment (id=491)
Patch against DMD2 svn 240.

The attached patch allows usage of $ inside opIndex and opIndexAssign in
structs and classes.
Any usage of $ becomes a call to an opDollar function.
If multi-dimensional indexing is possible, the $ symbol instantiates a template
called opDollar(int dim)().

x[ $-3, $-5, $-6] becomes  x.opIndex(x.opDollar!(0)() - 3, x.opDollar!(1)() -
5, x.opDollar!(2)() -6);

Note that since opDollar is a template, it may return different types for
different indices...

As a convenience, if a class or struct ONLY supports single-dimension indexing,
a non-templated opDollar() can be used instead.

x[ $-5 ]  can become   x.opIndex( x.opDollar() - 5 );

(If a opDollar!(int n)() is available, it will be used instead. There's no
ambiguity: the compiler won't let you define both template and function
opDollar, since they both have no arguments).

Some implementation notes:
(1) $ is evaluated lazily for each dimension.  x[4,  $+3*$ - foo($), 6] will
only make one call to opDollar.
(2) BUG 3326: "$ in delegate literal causes Access Violation" does NOT apply to
this code. You can do all kinds of nasty stuff with $ and it seems to work.
(3) It is possible to nest multi-dimensional indexing. x[$-2, y[$-6, $-9], $-2]
works.
(4) I have NOT implemented $ inside opSlice(), opSliceAssign().
It could be done, but I believe those language features need work. They don't
permit multi-dimensional slicing. I think they should be removed, and the
functionality folded into opIndex.
(5) How it works:
x[ $-3, 5, $-6]= "abc" actually becomes:
x.opIndexAssign("abc", (auto __dollar = x.opDollar!(0)();, __dollar - 3), 5,
(auto __dollar = x.opDollar!(2)(); _dollar - 6)).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 05 2009
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3474


Andrei Alexandrescu <andrei metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei metalanguage.com


--- Comment #1 from Andrei Alexandrescu <andrei metalanguage.com> 2009-11-05
08:13:37 PST ---
Great!

Any chance we can use "length" instead of "opDollar" throughout? It would
instantly match what arrays are currently doing and it would be a closer
description of the semantics of the operation.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 05 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3474



--- Comment #2 from Don <clugdbug yahoo.com.au> 2009-11-05 08:50:28 PST ---
(In reply to comment #1)
 Great!
 
 Any chance we can use "length" instead of "opDollar" throughout? It would
 instantly match what arrays are currently doing and it would be a closer
 description of the semantics of the operation.

Yes, the name doesn't make any difference. Although length() looks natural, I think length!(1)() looks a bit clumsy? The one-dimensional case is a degenerate form of the multi-dimensional case. Moreover, I suspect the template is not the interface you want in most cases: you often want to iterate over the dimensions. Probably in most cases, it'd be defined like: int opDollar(int n)() { return dim[n]; } Also there may be problems if you want to be able to use .length to change the dimensions. BTW you can use aliases. This works: struct Foo { int x; int length() { return x; } alias length opDollar; int opIndex(int k) { return x*k; } } void main() { Foo f = Foo(7); int x = foo[$-5]; assert(x== 2*7); } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 05 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3474



--- Comment #3 from Andrei Alexandrescu <andrei metalanguage.com> 2009-11-05
09:18:44 PST ---
(In reply to comment #2)
 (In reply to comment #1)
 Great!
 
 Any chance we can use "length" instead of "opDollar" throughout? It would
 instantly match what arrays are currently doing and it would be a closer
 description of the semantics of the operation.

Yes, the name doesn't make any difference. Although length() looks natural, I think length!(1)() looks a bit clumsy? The one-dimensional case is a degenerate form of the multi-dimensional case. Moreover, I suspect the template is not the interface you want in most cases: you often want to iterate over the dimensions. Probably in most cases, it'd be defined like: int opDollar(int n)() { return dim[n]; } Also there may be problems if you want to be able to use .length to change the dimensions. BTW you can use aliases. This works: struct Foo { int x; int length() { return x; } alias length opDollar; int opIndex(int k) { return x*k; } } void main() { Foo f = Foo(7); int x = foo[$-5]; assert(x== 2*7); }

I understand and have no further comments. Let's go with opDollar. (One suggestion if I may :o). In the 1-dimensional case, of a type defines no opDollar but does define length... you may want to rewrite $ to length. But probably that's too complicated a rule already.) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 05 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3474


Stewart Gordon <smjg iname.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |smjg iname.com


--- Comment #4 from Stewart Gordon <smjg iname.com> 2009-11-05 15:09:23 PST ---
(In reply to comment #1)
 Great!
 
 Any chance we can use "length" instead of "opDollar" throughout? It would
 instantly match what arrays are currently doing and it would be a closer
 description of the semantics of the operation.

I agree that "opDollar" is a bad choice of name, but so is "length". AIUI the point is for it to represent the end (or one past the end) of the array, rather than length. They correspond only in the case of 0-based arrays. This has come up before: http://www.digitalmars.com/d/archives/digitalmars/D/announce/Re_opDollar_12939.html -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 05 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3474



--- Comment #5 from Sobirari Muhomori <dfj1esp02 sneakemail.com> 2009-11-06
02:24:30 PST ---
 I agree that "opDollar" is a bad choice of name, but so is "length".  AIUI the
 point is for it to represent the end (or one past the end) of the array, rather
 than length.  They correspond only in the case of 0-based arrays.

It's elready defined semantics. $ means length. If you want different semantics, use different means to express it. Objects in container can be numbered from 1, numbering can have gaps, so $-1 can be meaningless, or entire collection can be unordered like hashtable, so the last element can be meaningless, or keytype can be of complex type, having nothing in common with numbers, you just use different means to work with it. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 06 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3474



--- Comment #6 from Stewart Gordon <smjg iname.com> 2009-11-06 06:43:47 PST ---
(In reply to comment #5)
 I agree that "opDollar" is a bad choice of name, but so is 
 "length".  AIUI the point is for it to represent the end (or one 
 past the end) of the array, rather than length.  They correspond 
 only in the case of 0-based arrays.

It's elready defined semantics. $ means length.

It's defined only on built-in linear arrays: http://www.digitalmars.com/d/2.0/arrays.html "Within the [ ] of a static or a dynamic array, the variable length is implicitly declared and set to the length of the array. The symbol $ can also be so used." Try it on AAs and see for yourself. (Sidenote: I thought the implicitly declared length was deprecated.) Moreover, FAIK, it may have been described this way only for simplicity, as Walter never expected to make it overloadable for custom types where "length" and "index one after the end" are distinct.
 If you want different semantics, use different means to express it.  
 Objects in container can be numbered from 1, numbering can have 
 gaps, so $-1 can be meaningless,

You're giving me exactly the already-known reasons $ ought to be defined along the lines of "end" rather than "length". It's probably how most D programmers think of it, because the main use for $ is to index relative to the end of an array. And so, if we start encouraging programmers to make $ mean the number of elements in a non-0-based array, sparse array or whatever, it'll get confusing. I certainly can't see any reason for keeping it as "length". And it would break 0% of existing code to change it now. As for "numbering can have gaps", there are at least two cases to consider: - indexes are spaced by a constant interval k, IWC [$-k] feels a natural way of referring to the final element analogous to [$-1] for standard arrays - indexes are (or may be) irregularly spaced, IWC what $ should mean, if anything, is harder to define
 or entire collection can be unordered like hashtable, so the last 
 element can be meaningless, or keytype can be of complex type, 
 having nothing in common with numbers, you just use different means 
 to work with it.

IWC you would probably not define $ at all. If there's any problem with that, I can't see it.... -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 06 2009
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3474


Adrian Matoga <epi atari8.info> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |epi atari8.info


--- Comment #7 from Adrian Matoga <epi atari8.info> 2010-08-08 06:19:55 PDT ---
Any solution of this? Currently (DMD 2.047) both length and opDollar give
"undefined identifier __dollar".

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Aug 08 2010