Intrinsics, std.bind problems, list comphrensions, recursivity test

Tom S h3r3tic at remove.mat.uni.torun.pl
Fri Aug 24 04:14:12 PDT 2007


bearophile wrote:
> import std.stdio, std.bind, std.traits, std.random;
> 
> int randInt(int min, int max) {
>   int k, n;
>   n = (max - min) + 1;
>   k = cast(int)(n * (rand() / (uint.max + 1.0)));
>   return (k == n) ? k + min - 1 : k + min;
> }
> 
> int randInt(int max) {
>   int k, n;
>   n = max + 1;
>   k = cast(int)(n * (rand() / (uint.max + 1.0)));
>   return (k == n) ? k - 1 : k;
> }
> 
> void main() {
>   // This line:
>   // auto rnd = bind(&randInt, 100);
> 
>   // Raises:
>   // ...\std\bind.d(395): static assert  is false

Yup, because Bind extracts type info from the passed delegate / 
function, and in this case it has two options. I'll try to see if I 
could somehow make it 'guess', basing on the number of parameters, which 
type to expect, but there might be problems with it. Anyway, the 
solution is to tell it which function pointer to choose, by using a cast.

> 
>   // Line 394-395 of std.bind.d:
>   // // make sure we'll copy all args the function is going to need
>   // static assert (res >= minFuncArgs);
> 
>   auto rnd100 = bind(&randInt, 0, 99);
> 
>   writefln( typeid(typeof(rnd100)) , '\n');
>   // Prints:
>   // std.bind.BoundFunc!(int(*)(int min, int max),NullAlias,Tuple!(int,int) ).BoundFunc

bind() doesn't return a delegate, it returns a BoundFunc object. Access 
the delegate by using .ptr(). Otherwise, opCall can be used on the 
object, but traits doesn't work on it


>   writefln(rnd100(), ' ', rnd100(), '\n'); // OK
> 
>   // This line:
>   // ReturnType!(typeof(rnd100)) x;
> 
>   // Raises:
>   // ...\std\traits.d(34): alias std.traits.ReturnType!(BoundFunc).ReturnType recursive alias declaration
> 
>   static if (is(rnd100 TyOut == return)) {
>     TyOut x;
>     writefln(typeid(typeof(x)));
>   } else
>     writefln("No return"); // Prints this
> }
> 
> (In the end I have simply solved the problem without std.bind, defining a lambda function.)

And here's the solution with Bind:

// ----
import std.stdio, std.bind, std.traits, std.random;

int randInt(int min, int max) {
   writefln(`rand1`);
   int k, n;
   n = (max - min) + 1;
   k = cast(int)(n * (rand() / (uint.max + 1.0)));
   return (k == n) ? k + min - 1 : k + min;
}

int randInt(int max) {
   writefln(`rand2`);
   int k, n;
   n = max + 1;
   k = cast(int)(n * (rand() / (uint.max + 1.0)));
   return (k == n) ? k - 1 : k;
}

void main() {
   // This line:
   auto rnd = bind(cast(int function(int))&randInt, 100).ptr();
   rnd();
   auto rnd100 = bind(&randInt, 0, 99).ptr();

   writefln( typeid(typeof(rnd100)) , '\n');
   writefln(rnd100(), ' ', rnd100(), '\n'); // OK

   ReturnType!(typeof(rnd100)) x;
   writefln(typeid(typeof(x)));
}
// ----


Cheers!


-- 
Tomasz Stachowiak
http://h3.team0xf.com/
h3/h3r3tic on #D freenode


More information about the Digitalmars-d-learn mailing list