On Tuesday, 27 May 2014 at 20:02:34 UTC, Meta wrote:
On Tuesday, 27 May 2014 at 19:39:23 UTC, Idan Arye wrote:
Hashing the function body is not enough - you must also
consider the closure!
template Template(alias func){
bool Template=func();
}
void foo(){
int a;
writeln(Template!(()=>is(typeof(a) : char))); //prints
"false"
}
void bar(){
char a;
writeln(Template!(()=>is(typeof(a) : char))); //prints
"true"
}
If two delegates must have exactly the same scope, the
usefulness of the hashing will be quite limited, but in many
cases the same lambda can be declared in different scopes and
still be the same. It all depends on how the lambda uses the
closure - and checking this will be quite hard to implement...
If I remember correctly, the main use-case of comparing lambda
functions was for cases like this:
auto rb1 = make!(RedBlackTree!(int, (a, b) => a < b))([4, 2, 3,
1]);
auto rb2 = make!(RedBlackTree!(int, (a, b) => a < b))([4, 2, 3,
1]);
assert(is(typeof(rb1) == typeof(rb2))); //FAIL
assert(rb1 == rb2); //FAIL
Note that this code passes if you define a top-level function
"less" and pass it to make. Functions don't have function
pointers, only delegates, so as a first step we could implement
hashing for functions, which don't have to deal with all this
context pointer business. Also, couldn't you achieve the same
for delegates if you specify that only @pure @nogc delegates
can be compared?
Well, it won't work for the example that opened this
thread(converted to use lambdas).
As for limiting the delegate version to ones that use @pure and
@nogc, take another look at my example. The lambdas don't
allocate anything so they're obviously @nogc. As for @pure, they
doesn't have any side effects, and depend only on their
arguments(they don't have arguments, and they are constant
functions) and their scope(which happens to be mutable, but you
could easily make it immutable and nothing will change).