Passing $ as a function argument
Simen Kjærås
simen.kjaras at gmail.com
Tue Oct 16 12:20:43 UTC 2018
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
More information about the Digitalmars-d
mailing list