Andrei Alexandrescu:

http://www.infoq.com/presentations/Generic-Programming-Galore-Using-D

It was a quite good talk.

Slide 13: very good, I am asking for min([1, 3, 5)) for a lot of time :-) (http://d.puremagic.com/issues/show_bug.cgi?id=4705 ).

I hope to see those new min/max/argMin/argMax functions in Phobos.

I'd also like the mins()/maxs() functions, as explained in Issue 4705, their need is common. I have added some use cases there.

(But your code doesn't work with opApply, so it doesn't work with everything as the slide says).

------------------------------

Slide 15:

auto m = argmin!((x) { return x.length;})(s);

As deadalnix notes, that was a good place to show the new D lambda template syntax and UCFS:

auto m = s.argmin!(x => x.length)();

But it also shows why Python (unlike Ruby) uses a free function for length (that calls a __len__ standard method on objects and built-ins), it allows you to write that code with no need of lambdas (it also shows why Python named arguments are nice):

m = min(s, key=len)

So in D to avoid defining a lambda I sometimes use walkLength as free function (but I have to keep in mind it gives different results on narrow strings!):

auto m = s.argmin!walkLength();

And maybe "argMin" name is more fitting in D than "argmin".

----------------------------

[Attention, uncooked ideas ahead]

Creating a good min() is not so easy. When I did create the dlibs1 in D1 I didn't know this, so I thought of myself as a not so good enough programmer for finding it not so easy to create the min/max functions :-)


At about 40.00 of your talk there was an interesting question and answer. D sees 255 on default as an integer literal:

auto x = 255;
static assert(is(typeof(x) == int));


But D also accepts this, because D knows this is a valid ubyte literal too, it fits in the ubyte interval:

ubyte x = 255;

The D compiler even accepts this with no errros or warnings, requiring no cast to assign z:

void main(string[] args) {
    uint x;
    ubyte y = cast(ubyte)args.length;
    ubyte z = x % y;
}


(A bug on this: http://d.puremagic.com/issues/show_bug.cgi?id=7834 ).


So another possible desiderata for a 'dream' min() function is this to compile, with no need of a cast in the user code:


void main(string[] args) {
    ubyte u = min(args.length, 255);
}


To allow this I think D needs some more static introspection/skills. The template of the min() function needs to be informed not just that the second argument is of type int, but also that it's a literal (or value known at compile time witn no need of running compile-time code to compute it, this is a requirement of the way D CTFE works), and it also fits in an ubyte range.

The result of that min() is of type size_t, so this is true (so the min of an unsigned short and an unsigned int is an unsigned int type still. Types and their ranges are orthogonal things):

auto u = min(args.length, 255);
static assert(is(typeof(u) == size_t));


But this also compiles because the compiler knows that despite the result of that min() call is a size_t the compile-time range of that size_t value fits inside a ubyte range too (just like for the built-in literal 255 that the compiler knows has a range that fits in an ubyte too):

ubyte u = min(args.length, 255);

So I think this kind of code needs a way to tell statically:
- The actual statically known range of a compile-time known integral value. - It also needs the ability to _assign_ a statically known range to an integer value. To make things simpler the compiler is not required to prove that this is a correct assignment, it accepts it with an act of faith.

Opionally I'd also like a way to tell, from inside the template:
- If a template argument is a literal (or it's a value known statically with no need to run compile-time code); - If the result of the function is assigned to a variable or not (if this information is used, then the template instantiates itself again in two variants, according to the boolean result of this query)).


I think a first step is to have something like this, to call from user code the interval analysis engine inside the D compiler. I think this just is just a way to expose to user code stuff already existing inside the compiler, so I think this requires only a small amount of compiler code to be added (I it's better for the result to be an interval closed on the right, unlike most other intervals in D):

uint x = ...;
__traits(interval, x & ubyte.max) ===> TypeTuple!(0, 255)


That alone is not enough to implement that "dream min". Because if you do this:

void foo(T)(T x) {
    writeln([__traits(interval, x)]);
}
void main() {
    foo(255);
}


I think it prints this, because the result of interval analysis gets lot when the expression ends or at function call point:

[-2147483648, 2147483647]

Bye,
bearophile

Reply via email to