Thread overview
Re: Why is std.algorithm.reduce impure?
Mar 06, 2012
H. S. Teoh
Mar 06, 2012
Adam D. Ruppe
Mar 06, 2012
H. S. Teoh
Mar 07, 2012
bearophile
Mar 06, 2012
H. S. Teoh
Mar 07, 2012
Jonathan M Davis
Mar 07, 2012
Simen Kjærås
Mar 07, 2012
Timon Gehr
Mar 07, 2012
Jonathan M Davis
Mar 07, 2012
Jonathan M Davis
March 06, 2012
On Tue, Mar 06, 2012 at 11:42:00PM +0100, Adam D. Ruppe wrote:
> On Tuesday, 6 March 2012 at 22:39:20 UTC, H. S. Teoh wrote:
> >Why is std.algorithm.reduce not marked pure?
> 
> It doesn't have to be - templates are inferred to be
> pure or not.
> 
> If you take the const off that signature, your example works in today's dmd.

Oh? what's wrong with the const?


T

-- 
Don't modify spaghetti code unless you can eat the consequences.
March 06, 2012
On Tuesday, 6 March 2012 at 22:48:30 UTC, H. S. Teoh wrote:
> Oh? what's wrong with the const?

test10.d(3): Error: function test10.product without 'this' cannot be const/immutable

It works if you put parens on it:

        pure const(int) product(int[] args) {


Without the parenthesis, D wants to apply it to this,
like if you write void foo() const {} in C++.

The reason here is most the attributes are at the
beginning, which is cool because this works:

const {
  void foo() {}
  int bar() {}
}

etc.


But if you put parens on it, it specifically applies
to the int.
March 06, 2012
On Tue, Mar 06, 2012 at 11:51:05PM +0100, Adam D. Ruppe wrote:
> On Tuesday, 6 March 2012 at 22:48:30 UTC, H. S. Teoh wrote:
> >Oh? what's wrong with the const?
> 
> test10.d(3): Error: function test10.product without 'this' cannot be
> const/immutable
> 
> It works if you put parens on it:
> 
>         pure const(int) product(int[] args) {
> 
> 
> Without the parenthesis, D wants to apply it to this,
> like if you write void foo() const {} in C++.

But why can't 'this' be const? For example, why does the compiler reject this:

	class A {
		int[] data;
		pure const int sum() {
			return reduce!"a*b"(data);
		}
	}

I'm not modifying data at at all, so why should it be an error?


T

-- 
Don't modify spaghetti code unless you can eat the consequences.
March 06, 2012
On Tue, Mar 06, 2012 at 03:00:16PM -0800, H. S. Teoh wrote: [...]
> But why can't 'this' be const? For example, why does the compiler reject this:
> 
> 	class A {
> 		int[] data;
> 		pure const int sum() {
> 			return reduce!"a*b"(data);
> 		}
> 	}
> 
> I'm not modifying data at at all, so why should it be an error?
[...]

Actually, nevermind that. Looks like a compiler bug that got fixed in dmd, but hasn't been pulled into gdc yet. I'll just have to be patient. :-)


T

-- 
A mathematician is a device for turning coffee into theorems. -- P. Erdos
March 07, 2012
On Tuesday, March 06, 2012 14:41:01 H. S. Teoh wrote:
> Why is std.algorithm.reduce not marked pure? It makes it impossible to do things like this:
> 
> pure const int product(int[] args) {
> return reduce!"a * b"(args);
> }

You'd have to look through the implementation and possibly tweak it to figure it out. All it takes is _one_ thing in there which isn't considered pure, and reduce won't be pure.

Glancing at it, I suspect that its use of emplace is the culprit. emplace uses memcpy in some of its overloads, and memcpy probably isn't marked as pure, since it's a C function. It theoretically _could_ be marked as pure - and arguably should be - but I very much doubt that it is right now.

It really takes very little for something to be impure, and optimizations often do it, because they end up using low-level constructs which aren't pure - some of which could be but aren't and others which probably can't be. More effort needs to be made in sorting out the purity of a number of the low-level constructs. Appender, for instance, screws up a lot of the string stuff, because it isn't pure. And it's far from the sole culprit.

- Jonathan M Davis
March 07, 2012
H. S. Teoh:

> But why can't 'this' be const? For example, why does the compiler reject this:
> 
> 	class A {
> 		int[] data;
> 		pure const int sum() {
> 			return reduce!"a*b"(data);
> 		}
> 	}
> 
> I'm not modifying data at at all, so why should it be an error?

I think it's a small bug in std.algorithm.reduce, is this in Bugzilla already?


import std.algorithm: reduce;
void main() {
    const data = [2, 3, 4];
    int r1 = reduce!q{a * b}(0, data); // OK
    int r2 = reduce!q{a * b}(data);
}



In std.algorithm.reduce there is also this (now bug 2443 is fixed) at about line 723:

            // For now, just iterate using ref to avoid unnecessary copying.
            // When Bug 2443 is fixed, this may need to change.
            foreach(ref elem; r)
            {
                if(initialized)

Bye,
bearophile
March 07, 2012
On Wed, 07 Mar 2012 01:41:22 +0100, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> It really takes very little for something to be impure, and optimizations
> often do it, because they end up using low-level constructs which aren't pure
> - some of which could be but aren't and others which probably can't be.

Just so this is clear - no optimization of the compiler is going to change
the purity of a function. An optimization on the part of the programmer
(like using appender) might, though.
March 07, 2012
On 03/07/2012 05:29 PM, Simen Kjærås wrote:
> On Wed, 07 Mar 2012 01:41:22 +0100, Jonathan M Davis
> <jmdavisProg@gmx.com> wrote:
>
>> It really takes very little for something to be impure, and optimizations
>> often do it, because they end up using low-level constructs which
>> aren't pure
>> - some of which could be but aren't and others which probably can't be.
>
> Just so this is clear - no optimization of the compiler is going to change
> the purity of a function. An optimization on the part of the programmer
> (like using appender) might, though.

Appender must become pure.
March 07, 2012
On Wednesday, March 07, 2012 17:58:43 Timon Gehr wrote:
> On 03/07/2012 05:29 PM, Simen Kjærås wrote:
> > On Wed, 07 Mar 2012 01:41:22 +0100, Jonathan M Davis
> > 
> > <jmdavisProg@gmx.com> wrote:
> >> It really takes very little for something to be impure, and optimizations
> >> often do it, because they end up using low-level constructs which
> >> aren't pure
> >> - some of which could be but aren't and others which probably can't be.
> > 
> > Just so this is clear - no optimization of the compiler is going to change the purity of a function. An optimization on the part of the programmer (like using appender) might, though.
> 
> Appender must become pure.

Most definitely. A variety of things which are currently impure must become pure. Some things which didn't used to be pure still are, but there's still plenty left that need to be sorted out.

- Jonathan M Davis
March 07, 2012
On Wednesday, March 07, 2012 17:29:24 Simen Kjærås wrote:
> On Wed, 07 Mar 2012 01:41:22 +0100, Jonathan M Davis <jmdavisProg@gmx.com>
> 
> wrote:
> > It really takes very little for something to be impure, and optimizations
> > often do it, because they end up using low-level constructs which aren't
> > pure
> > - some of which could be but aren't and others which probably can't be.
> 
> Just so this is clear - no optimization of the compiler is going to change the purity of a function. An optimization on the part of the programmer (like using appender) might, though.

I didn't say that it did, though maybe I wasn't clear enough. Optimizations of the _algorithms_ involved can make a function impure - such as use Appender instead of ~= when building arrays.

- Jonathan M Davis