| |
| Posted by Ali Çehreli in reply to realhet | PermalinkReply |
|
Ali Çehreli
Posted in reply to realhet
| On 5/12/22 04:57, realhet wrote:
> //this would be nicer, but not works
> iota(st, en, day).each!writeln;
For others, the problem is, iota does have a version that works with user types but not one that parameterizes 'step'. An oversight?
> My question is, is there a way to 'extend' the functionality of the
> std.iota() function or it is better to come up with a unique name for
> this special 'iota' functionality?
I think ioat can be improved to work with user 'step' types as I did below.
> Is this a good practice
I don't care whether it is good practice or not. :) The following is what you meant anyway and seems to work. I added 6 comments:
import std.stdio;
import std.range;
import std.algorithm;
struct Duration {
ulong value;
}
struct DateTime {
Duration sinceEpoch; // Quickest implementation for this post
auto opOpAssign(string op)(Duration dur)
if (op == "+") {
return DateTime(Duration(sinceEpoch.value += dur.value));
}
}
void main() {
const st = DateTime(Duration(0));
const en = DateTime(Duration(10));
const step = Duration(1);
// (0) I think D should not insist on 'const'
// when copying types that have no indirections.
// We shouldn't need the cast() below in this case.
//
// Alternatively, the implementation of iota()
// could use Unqual after detecting B has no
// indirections. That would be better for the
// user but again, the language should copy
// to non-const by-default. But then, I am
// sure there would be cases where an unexpected
// function overload might be selected in some
// cases.
iota(cast()st, en, step).each!writeln;
}
// I adapted the following template from my
// /usr/include/dlang/dmd/std/range/package.d
// and then:
// (1) Added 'S step'
auto iota(B, E, S)(B begin, E end, S step)
// (2) Removed for now
// if (!isIntegral!(CommonType!(B, E)) &&
// !isFloatingPoint!(CommonType!(B, E)) &&
// !isPointer!(CommonType!(B, E)) &&
// is(typeof((ref B b) { ++b; })) &&
// (is(typeof(B.init < E.init)) || is(typeof(B.init == E.init))) )
{
static struct Result
{
B current;
E end;
S step; // (3) Added
@property bool empty()
{
static if (is(typeof(B.init < E.init)))
return !(current < end);
else static if (is(typeof(B.init != E.init)))
return current == end;
else
static assert(0);
}
@property auto front() { return current; }
void popFront()
{
assert(!empty);
// (4) Used += instead of ++current
// This can be improved to use the other
// method a.l.a. "design by introspection".
current += step;
}
}
// (5) Added step
return Result(begin, end, step);
}
Ali
|