View mode: basic / threaded / horizontal-split · Log in · Help
February 20, 2012
A inner pure function problem
This code looks interesting (maybe this code is also able to spot a bug in DMD, or it is able to show something I have not fully understood in D). Do you know if there are interesting ways to compile it?


T outer(T)(T function(in T) pure foo) pure {
   pure int inner() {
       return foo(5); // line 3
   }
   return inner();
}
int sqr(in int x) pure {
   return x * x;
}
void main() {
   assert(outer(&sqr) == 25); // line 14
}


test.d(3): Error: pure nested function 'inner' cannot access mutable data 'foo'
test.d(11): Error: template instance test.outer!(int) error instantiating



This compiles, but it's not nice:


int sqr(in int x) pure {
   return x * x;
}
immutable sqrPtr = &sqr;
auto outer(typeof(sqrPtr) foo) pure {
   pure int inner() {
       return foo(5);
   }
   return inner();
}
void main() {
   assert(outer(sqrPtr) == 25);
}

Bye and thank you,
bearophile
February 20, 2012
Re: A inner pure function problem
On 02/20/2012 02:26 PM, bearophile wrote:
> This code looks interesting (maybe this code is also able to spot a bug in DMD, or it is able to show something I have not fully understood in D). Do you know if there are interesting ways to compile it?
>
>
> T outer(T)(T function(in T) pure foo) pure {
>      pure int inner() {
>          return foo(5); // line 3
>      }
>      return inner();
> }
> int sqr(in int x) pure {
>      return x * x;
> }
> void main() {
>      assert(outer(&sqr) == 25); // line 14
> }
>
>
> test.d(3): Error: pure nested function 'inner' cannot access mutable data 'foo'
> test.d(11): Error: template instance test.outer!(int) error instantiating
>
>
>
> This compiles, but it's not nice:
>
>
> int sqr(in int x) pure {
>      return x * x;
> }
> immutable sqrPtr =&sqr;
> auto outer(typeof(sqrPtr) foo) pure {
>      pure int inner() {
>          return foo(5);
>      }
>      return inner();
> }
> void main() {
>      assert(outer(sqrPtr) == 25);
> }
>
> Bye and thank you,
> bearophile

Well, rejecting the code without the immutable qualifier is 'necessary' 
in order to preserve the purity of the inner function.

This is probably the best way to get it to compile:

T outer(T)(T function(in T) pure foo) pure {
    immutable fooTick = foo;
    pure int inner() {
        return fooTick(5); // line 3
    }
    return inner();	
}
int sqr(in int x) pure {
    return x * x;
}
void main() {
    assert(outer(&sqr) == 25); // line 14
}

The fact that qualifying the parameter with immutable directly causes a 
matching failure in IFTI appears to be a bug.
(you might not want to do this anyway, because it causes the matching 
level to shrink from 'exact' to 'with conversion to const' and therefore 
might interfere with eventual overloads.)
February 20, 2012
Re: A inner pure function problem
Timon Gehr:

> T outer(T)(T function(in T) pure foo) pure {
>      immutable fooTick = foo;
>      pure int inner() {
>          return fooTick(5); // line 3
>      }
>      return inner();	
> }
> int sqr(in int x) pure {
>      return x * x;
> }
> void main() {
>      assert(outer(&sqr) == 25); // line 14
> }

Nice.


> The fact that qualifying the parameter with immutable directly causes a 
> matching failure in IFTI appears to be a bug.

http://d.puremagic.com/issues/show_bug.cgi?id=7554

Thank you, bye,
bearophile
Top | Discussion index | About this forum | D home