On Sunday, 14 October 2018 at 15:27:07 UTC, Michael Coulombe
wrote:
On Sunday, 14 October 2018 at 14:35:36 UTC, lngns wrote:
On Sunday, 14 October 2018 at 13:18:37 UTC, lngns wrote:
That would require introducing a new type
Or just use int with a negative number... That's how it's done
in some dynamic languages.
But my point is that it should be compatible with pre-existing
code using unsigned indices somehow. I don't think that is
possible.
Another way to do this with UFCS:
// write-once library wrapper
struct Indexer(R) {
R r;
auto opDollar() { return r.length; }
auto opIndex(size_t i) { return r[i]; }
}
auto indexer(R)(R r) { return Indexer(r); }
// rewrite index parameter => return wrapped range
auto foo()
{
auto arr = (...);
return indexer(arr);
}
// easy-to-use result
auto end = foo[$-1];
Didn't feel like making a full expression tree thing, so feel
free to extend this:
struct Index {
struct Op {
string op;
int value;
void apply(ref size_t val) {
switch (op) {
case "+": val += value; break;
case "-": val -= value; break;
case "*": val *= value; break;
case "/": val /= value; break;
case "%": val %= value; break;
default: assert(false);
}
}
}
Op[] ops;
bool fromEnd;
this(bool b) { fromEnd = b; }
this(size_t i) {
ops ~= Op("+", i);
}
static Index opDollar() {
return Index(true);
}
static Index opIndex(Index idx) {
return idx;
}
static Index opIndex(size_t idx) {
return Index(idx);
}
auto opBinary(string op)(int rhs) {
Index result = this;
result.ops ~= Op(op, rhs);
return result;
}
auto value(size_t length) {
size_t result = fromEnd ? length : 0;
foreach (e; ops)
e.apply(result);
return result;
}
}
struct Indexer(R) {
R r;
alias r this;
Index opDollar() {
return Index(true);
}
auto opIndex(Index idx) {
return r[idx.value(r.length)];
}
auto opIndex(size_t idx) {
return r[idx];
}
}
auto indexer(R)(R r) {
return Indexer!R(r);
}
unittest {
auto a = Index[$-2]; // Will always point to next-to-last
element.
auto arr = [1,2,3,4,5,6,7,8,9].indexer; // Wrap access.
assert(arr[0] == 1); // Regular access still works.
assert(arr[a] == 8); // Look ma, I'm using $!
assert(arr[Index[$-1]] == 9); // Look ma, I'm using $!
}
--
Simen