Thread overview
Re: Infer purity of functions too?
Jul 18, 2011
bearophile
Jul 18, 2011
Jonathan M Davis
Jul 21, 2011
bearophile
Jul 21, 2011
Jonathan M Davis
Jul 21, 2011
Mafi
July 18, 2011
> Example: if a not pure function sqr is called by both a not pure template bar and by a pure function foo, the compiler raises an error in foo, because sqr is not pure, but compiles the pure main because sqr called by bar is seen as pure :-)

This seems quite useful for delegates given to higher order functions:

int spam(in int x) pure { return x * 3; }
auto squares = map!((int x){ return spam(x) * x; })(iota(10));

With this idea squares is usable in a pure function too, because the map template infers the given delegate as pure.

Otherwise you need to write:

int spam(in int x) pure { return x * 3; }
auto squares = map!((int x) pure { return spam(x) * x; })(iota(10));

Bye,
bearophile
July 18, 2011
On 2011-07-18 16:07, bearophile wrote:
> > Example: if a not pure function sqr is called by both a not pure template bar and by a pure function foo, the compiler raises an error in foo, because sqr is not pure, but compiles the pure main because sqr called by bar is seen as pure :-)
> 
> This seems quite useful for delegates given to higher order functions:
> 
> int spam(in int x) pure { return x * 3; }
> auto squares = map!((int x){ return spam(x) * x; })(iota(10));
> 
> With this idea squares is usable in a pure function too, because the map template infers the given delegate as pure.
> 
> Otherwise you need to write:
> 
> int spam(in int x) pure { return x * 3; }
> auto squares = map!((int x) pure { return spam(x) * x; })(iota(10));

I believe that there is some level of purity inference with delegates, but I don't know what the situation with that is exactly.

- Jonathan M Davis
July 21, 2011
Jonathan M Davis:

> I believe that there is some level of purity inference with delegates, but I don't know what the situation with that is exactly.

I didn't know/remember this, but it seems you are right, delegates too seem to receive purity inference. This has one downside too, this innocent-looking program doesn't compile:


import std.math;
void main() {
    auto funcs = [(int x){return x; },
                  (int x){return abs(x); }];
}


The error, DMD 2.054:

test.d(4): Error: incompatible types for ((__dgliteral1) ? (__dgliteral2)): 'int delegate(int x) pure nothrow' and 'int delegate(int x) nothrow'

How to solve this specific problem: I think abs() can be pure.

An example of a bit more general class of problems:

import std.math;
void main() {
    auto funcs = [&sin, &tan];
}


test.d(3): Error: incompatible types for ((& sin) ? (& tan)): 'real function(real x) pure nothrow @safe' and 'real function(real x) pure nothrow @trusted'

To solve this more generic class of problems the compiler has to give to the funcs array a common type (where possible), here int delegate(int x) pure nothrow[] is able to contain both kinds of delegates, and cast all the array delegates to the common type (I have a bug report about this in Bugzilla).

Bye,
bearophile
July 21, 2011
On 2011-07-20 17:01, bearophile wrote:
> Jonathan M Davis:
> > I believe that there is some level of purity inference with delegates, but I don't know what the situation with that is exactly.

I only know because when Walter initially made the purity inference changes, the commit mentioned delegates, and I had to ask whether it included templated functions. There's every possibility though that it needs some ironing out (or that other language features need some ironing) out for it to work in some cases though (as you appear to be running into).

- Jonathan M Davis
July 21, 2011
Am 21.07.2011 02:01, schrieb bearophile:
> Jonathan M Davis:
>
>> I believe that there is some level of purity inference with delegates, but I
>> don't know what the situation with that is exactly.
>
> I didn't know/remember this, but it seems you are right, delegates too seem to receive purity inference. This has one downside too, this innocent-looking program doesn't compile:
>
>
> import std.math;
> void main() {
>      auto funcs = [(int x){return x; },
>                    (int x){return abs(x); }];
> }
>
>
> The error, DMD 2.054:
>
> test.d(4): Error: incompatible types for ((__dgliteral1) ? (__dgliteral2)): 'int delegate(int x) pure nothrow' and 'int delegate(int x) nothrow'
>
> How to solve this specific problem: I think abs() can be pure.
>
> An example of a bit more general class of problems:
>
> import std.math;
> void main() {
>      auto funcs = [&sin,&tan];
> }
>
>
> test.d(3): Error: incompatible types for ((&  sin) ? (&  tan)): 'real function(real x) pure nothrow @safe' and 'real function(real x) pure nothrow @trusted'
>
> To solve this more generic class of problems the compiler has to give to the funcs array a common type (where possible), here int delegate(int x) pure nothrow[] is able to contain both kinds of delegates, and cast all the array delegates to the common type (I have a bug report about this in Bugzilla).
>
> Bye,
> bearophile

I would say the common type is int delegate(int) pure nothrow @trustd .