www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Type-Strict Indexes: IndexedBy

reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
I'm trying to figure out how to implement a light-weight wrappr 
realizing type-safe indexing á lá Ada. Here's my first try:

struct Ix(T = size_t)
{
      safe pure:  nogc nothrow:
     this(T ix) { this._ix = ix; }
     alias _ix this;
     private T _ix = 0;
}

struct IndexedBy(R, I)
{
     auto ref opIndex(I ix) inout { return _r[ix]; }
     auto ref opSlice(I lower, I upper) inout { return _r[lower .. 
upper]; }
     R _r;
     alias _r this;
}

auto indexedBy(I, R)(R range)
{
     return IndexedBy!(R, I)(range);
}

unittest
{
     import std.stdio;
     auto x = [1, 2, 3];
     alias I = int;
     auto ix = x.indexedBy!I;
     ix[0] = 11;

     alias J = Ix!size_t;
     auto jx = x.indexedBy!J;
     jx[J(0)] = 11;              // should compile
     jx[0] = 11;                 // TODO how can I make this not 
compile?
}

My question now of course is:

How can I prevent

     jx[0] = 11;

from compiling?
Feb 16 2015
next sibling parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Monday, 16 February 2015 at 20:09:09 UTC, Nordlöw wrote:
 I'm trying to figure out how to implement a light-weight wrappr 
 realizing type-safe indexing á lá Ada. Here's my first try:
See also: https://github.com/nordlow/justd/blob/master/typecons_ex.d#L83
Feb 16 2015
prev sibling next sibling parent reply "anonymous" <anonymous example.com> writes:
On Monday, 16 February 2015 at 20:09:09 UTC, Nordlöw wrote:
 How can I prevent

     jx[0] = 11;

 from compiling?
Remove that `alias _r this;`. You don't want to forward opIndex, so you can't use alias this which forwards everything that doesn't compile. opDispatch may be an option to forward everything but opIndex.
Feb 16 2015
next sibling parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Monday, 16 February 2015 at 20:17:55 UTC, anonymous wrote:
 Remove that `alias _r this;`. You don't want to forward 
 opIndex, so you can't use alias this which forwards everything 
 that doesn't compile. opDispatch may be an option to forward 
 everything but opIndex.
Thanks!
Feb 16 2015
parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Monday, 16 February 2015 at 20:48:29 UTC, Nordlöw wrote:
 Thanks!
See also: http://forum.dlang.org/thread/akibggljgcmmacsbahmm forum.dlang.org
Feb 16 2015
prev sibling next sibling parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Monday, 16 February 2015 at 20:17:55 UTC, anonymous wrote:
 that doesn't compile. opDispatch may be an option to forward 
 everything but opIndex.
What about disable?
Feb 16 2015
prev sibling parent reply "Per =?UTF-8?B?Tm9yZGzDtnci?= <per.nordlow gmail.com> writes:
On Monday, 16 February 2015 at 20:17:55 UTC, anonymous wrote:
 Remove that `alias _r this;`. You don't want to forward 
 opIndex, so you can't use alias this which forwards everything 
 that doesn't compile. opDispatch may be an option to forward 
 everything but opIndex.
This looses most of the meaning of my idea. I still want my range to inherit all the powers of its wrapped range. Is there no way to disable member functions in D?
Feb 17 2015
parent reply "anonymous" <anonymous example.com> writes:
On Tuesday, 17 February 2015 at 13:38:41 UTC, Per Nordlöw wrote:
 This looses most of the meaning of my idea. I still want my 
 range to inherit all the powers of its wrapped range.

 Is there no way to disable member functions in D?
I hadn't thought of disable. Played around with it a bit. The following code seems to work. I didn't really test it or think very hard about it, though. Regarding opIndexAssign: Without it, alias this jumps in on assignments, and the ref opIndex is not considered. This may be a compiler bug. Be aware that with alias this, IndexedBy!(R, I) implicitly converts to R. So it's easy to (accidentally) fall back to a plain R, where nothing is ` disable`d. I don't know if this is desirable or not. ---- struct Ix(T = size_t) { safe pure: nogc nothrow: this(T ix) { this._ix = ix; } alias _ix this; private T _ix = 0; } struct IndexedBy(R, I) { auto ref opIndex(I ix) inout { return _r[ix]; } void opIndexAssign(V)(V value, I ix) {_r[ix] = value;} alias RI = size_t; /* TODO: Extract this from R somehow. */ static if(!is(RI == I)) { disable void opIndex(RI i); disable void opIndexAssign(V)(V value, RI i); } R _r; alias _r this; } auto indexedBy(I, R)(R range) { return IndexedBy!(R, I)(range); } unittest { import std.stdio; auto x = [1, 2, 3]; alias I = int; auto ix = x.indexedBy!I; ix[0] = 11; alias J = Ix!size_t; auto jx = x.indexedBy!J; jx[J(0)] = 11; static assert(!__traits(compiles, (jx[0] = 11))); } ----
Feb 17 2015
parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Tuesday, 17 February 2015 at 15:02:05 UTC, anonymous wrote:
 I hadn't thought of  disable. Played around with it a bit. The 
 following code seems to work. I didn't really test it or think 
 very hard about it, though.
Superb! I'd like to see this getting into std.typecons. Having this in the language will attract (more) Ada programmers to D. Should I do PR for std.typecons.[iI]ndexedBy?
Feb 17 2015
next sibling parent reply "anonymous" <anonymous example.com> writes:
On Tuesday, 17 February 2015 at 19:46:09 UTC, Nordlöw wrote:
 Superb! I'd like to see this getting into std.typecons.

 Having this in the language will attract (more) Ada programmers 
 to D.

 Should I do PR for std.typecons.[iI]ndexedBy?
I'm not familiar with Ada, and I don't immediately see what indexedBy is good for. So maybe gather some examples where it's beneficial, before going for Phobos.
Feb 18 2015
parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Wednesday, 18 February 2015 at 12:44:22 UTC, anonymous wrote:
 Should I do PR for std.typecons.[iI]ndexedBy?
I'm not familiar with Ada, and I don't immediately see what indexedBy is good for. So maybe gather some examples where it's beneficial, before going for Phobos.
Ok, I have a use case in one my applications I'll bring up. Thanks for now.
Feb 18 2015
prev sibling parent "Tobias Pankrath" <tobias pankrath.net> writes:
 Having this in the language will attract (more) Ada programmers 
 to D.
“Having this or that will attract (XY)-programmers / magically make D successful in niche Z” is an argument too weak for phobos inclusion, IMO.
Feb 18 2015
prev sibling parent "Tobias Pankrath" <tobias pankrath.net> writes:
On Monday, 16 February 2015 at 20:09:09 UTC, Nordlöw wrote:
 I'm trying to figure out how to implement a light-weight wrappr 
 realizing type-safe indexing á lá Ada. Here's my first try:

 struct Ix(T = size_t)
 {
      safe pure:  nogc nothrow:
     this(T ix) { this._ix = ix; }
     alias _ix this;
     private T _ix = 0;
 }

 struct IndexedBy(R, I)
 {
     auto ref opIndex(I ix) inout { return _r[ix]; }
     auto ref opSlice(I lower, I upper) inout { return _r[lower 
 .. upper]; }
     R _r;
     alias _r this;
 }

 auto indexedBy(I, R)(R range)
 {
     return IndexedBy!(R, I)(range);
 }

 unittest
 {
     import std.stdio;
     auto x = [1, 2, 3];
     alias I = int;
     auto ix = x.indexedBy!I;
     ix[0] = 11;

     alias J = Ix!size_t;
     auto jx = x.indexedBy!J;
     jx[J(0)] = 11;              // should compile
     jx[0] = 11;                 // TODO how can I make this not 
 compile?
 }

 My question now of course is:

 How can I prevent

     jx[0] = 11;

 from compiling?
Did you actually try that? This does not compile because of c[13] struct IndexT { this(size_t s) { x = s; } size_t x; } struct Container { int opIndex(IndexT i) { return 12; } } void main() { auto it = IndexT(13); Container c; c[it]; c[13]; }
Feb 16 2015