www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - To help LDC/GDC

reply "bearophile" <bearophileHUGS lycos.com> writes:
I remember Walter saying two or more times that the semantics of 
D offers some optimization opportunities that probably are not 
yet used to try to reduce the run-time of D programs. Is Walter 
willing to write down a list of such opportunities? (Ideas from 
other persons are welcome). Maybe some LDC/GDC developer will 
make the GCC/LLVM back-ends use them. The implementation of those 
ideas will require some time, so later it's better to put the 
list in the D wiki.

Bye,
bearophile
Apr 06 2013
next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 6 April 2013 12:09, bearophile <bearophileHUGS lycos.com> wrote:

 I remember Walter saying two or more times that the semantics of D offers
 some optimization opportunities that probably are not yet used to try to
 reduce the run-time of D programs. Is Walter willing to write down a list
 of such opportunities? (Ideas from other persons are welcome). Maybe some
 LDC/GDC developer will make the GCC/LLVM back-ends use them. The
 implementation of those ideas will require some time, so later it's better
 to put the list in the D wiki.

 Bye,
 bearophile
This information could possibly be helpful. Though given that most of (gdc) codegen is on par with g++, there's probably not much on the list that isn't already detected by the backend optimisation passes. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Apr 08 2013
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/08/2013 10:29 AM, Iain Buclaw wrote:
 On 6 April 2013 12:09, bearophile <bearophileHUGS lycos.com
 <mailto:bearophileHUGS lycos.com>> wrote:

     I remember Walter saying two or more times that the semantics of D
     offers some optimization opportunities that probably are not yet
     used to try to reduce the run-time of D programs. Is Walter willing
     to write down a list of such opportunities? (Ideas from other
     persons are welcome). Maybe some LDC/GDC developer will make the
     GCC/LLVM back-ends use them. The implementation of those ideas will
     require some time, so later it's better to put the list in the D wiki.

     Bye,
     bearophile



 This information could possibly be helpful.  Though given that most of
 (gdc) codegen is on par with g++, there's probably not much on the list
 that isn't already detected by the backend optimisation passes.


 --
 Iain Buclaw

 *(p < e ? p++ : p) = (c & 0x0f) + '0';
Does GDC use the additional type information for optimization? Eg. if something is immutable, then aliasing issues do not have to be considered for it when reading and writing through multiple pointers repeatedly.
Apr 08 2013
next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 8 April 2013 10:06, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 04/08/2013 10:29 AM, Iain Buclaw wrote:

 On 6 April 2013 12:09, bearophile <bearophileHUGS lycos.com
 <mailto:bearophileHUGS lycos.**com <bearophileHUGS lycos.com>>> wrote:

     I remember Walter saying two or more times that the semantics of D
     offers some optimization opportunities that probably are not yet
     used to try to reduce the run-time of D programs. Is Walter willing
     to write down a list of such opportunities? (Ideas from other
     persons are welcome). Maybe some LDC/GDC developer will make the
     GCC/LLVM back-ends use them. The implementation of those ideas will
     require some time, so later it's better to put the list in the D wiki.

     Bye,
     bearophile



 This information could possibly be helpful.  Though given that most of
 (gdc) codegen is on par with g++, there's probably not much on the list
 that isn't already detected by the backend optimisation passes.


 --
 Iain Buclaw

 *(p < e ? p++ : p) = (c & 0x0f) + '0';
Does GDC use the additional type information for optimization? Eg. if something is immutable, then aliasing issues do not have to be considered for it when reading and writing through multiple pointers repeatedly.
It uses some type information, eg: const/immutable/wild -> qualified const. shared -> qualified volatile. shared + const/wild -> qualified const/volatile. Done nothing in regards to C 'restrict' optimisations. However the D array .ptr type could also be considered 'restrict' also. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Apr 08 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Monday, 8 April 2013 at 09:41:52 UTC, Iain Buclaw wrote:
 It uses some type information, eg:

 const/immutable/wild  -> qualified const.
 shared -> qualified volatile.
 shared + const/wild -> qualified const/volatile.
const/wild can be muted via aliasing. I'm not sure how GCC's backend understand const, but this seems unclear to me if this is correct.
 Done nothing in regards to C 'restrict' optimisations.  However 
 the D array
 .ptr type could also be considered 'restrict' also.
slices can alias each other. Same as above, is that correct ?
Apr 08 2013
next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 8 April 2013 12:41, deadalnix <deadalnix gmail.com> wrote:

 On Monday, 8 April 2013 at 09:41:52 UTC, Iain Buclaw wrote:

 It uses some type information, eg:

 const/immutable/wild  -> qualified const.
 shared -> qualified volatile.
 shared + const/wild -> qualified const/volatile.
const/wild can be muted via aliasing. I'm not sure how GCC's backend understand const, but this seems unclear to me if this is correct.
GCC's backend is pretty much C/C++ semantics. So the const qualifier is shallow, and does not guarantee that no mutations will occur. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Apr 08 2013
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On 8 April 2013 21:53, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 8 April 2013 12:41, deadalnix <deadalnix gmail.com> wrote:

 On Monday, 8 April 2013 at 09:41:52 UTC, Iain Buclaw wrote:

 It uses some type information, eg:

 const/immutable/wild  -> qualified const.
 shared -> qualified volatile.
 shared + const/wild -> qualified const/volatile.
const/wild can be muted via aliasing. I'm not sure how GCC's backend understand const, but this seems unclear to me if this is correct.
GCC's backend is pretty much C/C++ semantics. So the const qualifier is shallow, and does not guarantee that no mutations will occur.
But D makes no further guarantee. I don't see how const in D is any different than const in C++ in that sense? That's basically the concept of const, it's not a useful concept for optimisation, only immutable is.
Apr 08 2013
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 8 April 2013 at 12:39:58 UTC, Manu wrote:
 On 8 April 2013 21:53, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 8 April 2013 12:41, deadalnix <deadalnix gmail.com> wrote:

 On Monday, 8 April 2013 at 09:41:52 UTC, Iain Buclaw wrote:

 It uses some type information, eg:

 const/immutable/wild  -> qualified const.
 shared -> qualified volatile.
 shared + const/wild -> qualified const/volatile.
const/wild can be muted via aliasing. I'm not sure how GCC's backend understand const, but this seems unclear to me if this is correct.
GCC's backend is pretty much C/C++ semantics. So the const qualifier is shallow, and does not guarantee that no mutations will occur.
But D makes no further guarantee. I don't see how const in D is any different than const in C++ in that sense? That's basically the concept of const, it's not a useful concept for optimisation, only immutable is.
D const is transitive, surely that makes a difference/presents an opportunity?
Apr 08 2013
parent reply Manu <turkeyman gmail.com> writes:
On 8 April 2013 23:01, John Colvin <john.loughran.colvin gmail.com> wrote:

 On Monday, 8 April 2013 at 12:39:58 UTC, Manu wrote:

 On 8 April 2013 21:53, Iain Buclaw <ibuclaw ubuntu.com> wrote:

  On 8 April 2013 12:41, deadalnix <deadalnix gmail.com> wrote:
  On Monday, 8 April 2013 at 09:41:52 UTC, Iain Buclaw wrote:
  It uses some type information, eg:
 const/immutable/wild  -> qualified const.
 shared -> qualified volatile.
 shared + const/wild -> qualified const/volatile.


  const/wild can be muted via aliasing. I'm not sure how GCC's backend
understand const, but this seems unclear to me if this is correct. GCC's backend is pretty much C/C++ semantics. So the const qualifier
is shallow, and does not guarantee that no mutations will occur.
But D makes no further guarantee. I don't see how const in D is any different than const in C++ in that sense? That's basically the concept of const, it's not a useful concept for optimisation, only immutable is.
D const is transitive, surely that makes a difference/presents an opportunity?
No, I think that just makes it 'safer', or as many might say, "more annoying" ;)
Apr 08 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
Casting away D const is undefined behavior. It is still not for 
single-threaded C++11 code AFAIK. That may make an important 
difference for optimization opportunities.
Apr 08 2013
next sibling parent "Dicebot" <m.strashun gmail.com> writes:
On Monday, 8 April 2013 at 13:13:22 UTC, Dicebot wrote:
 Casting away D const is undefined behavior. It is still not for 
 single-threaded C++11 code AFAIK. That may make an important 
 difference for optimization opportunities.
Minor fix: It is undefined in C++11 to cast away const from pointer to data immutable by definition (like string literals), but that can't be known from function that accepts const argument.
Apr 08 2013
prev sibling parent "Jesse Phillips" <Jessekphillips+d gmail.com> writes:
On Monday, 8 April 2013 at 13:13:22 UTC, Dicebot wrote:
 Casting away D const is undefined behavior. It is still not for 
 single-threaded C++11 code AFAIK. That may make an important 
 difference for optimization opportunities.
Minor correction, it is undefined to modify a const reference.
Apr 08 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/8/2013 5:39 AM, Manu wrote:
 But D makes no further guarantee. I don't see how const in D is any different
 than const in C++ in that sense? That's basically the concept of const, it's
not
 a useful concept for optimisation, only immutable is.
In C++, it is legal to cast away const and mutate it. That is undefined behavior in D. A D compiler can assume, for example, that a const reference passed to a pure function will not mutate that reference, nor anything transitively referred to by that reference. No such assumption can be made like that in C++.
Apr 08 2013
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-04-09 05:30, Walter Bright wrote:

 In C++, it is legal to cast away const and mutate it. That is undefined
 behavior in D.
Didn't they change how const behaves in C++11, I'm thinking of this: http://channel9.msdn.com/posts/C-and-Beyond-2012-Herb-Sutter-You-dont-know-blank-and-blank -- /Jacob Carlborg
Apr 09 2013
parent "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 07:11:02 UTC, Jacob Carlborg wrote:
 On 2013-04-09 05:30, Walter Bright wrote:

 In C++, it is legal to cast away const and mutate it. That is 
 undefined
 behavior in D.
Didn't they change how const behaves in C++11, I'm thinking of this: http://channel9.msdn.com/posts/C-and-Beyond-2012-Herb-Sutter-You-dont-know-blank-and-blank
Yes, but it is changed only for multi-threaded code (because the very concept of concurrency is defined first in C++11). Single-thread semantics remain the same.
Apr 09 2013
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 9 April 2013 13:30, Walter Bright <newshound2 digitalmars.com> wrote:

 On 4/8/2013 5:39 AM, Manu wrote:

 But D makes no further guarantee. I don't see how const in D is any
 different
 than const in C++ in that sense? That's basically the concept of const,
 it's not
 a useful concept for optimisation, only immutable is.
In C++, it is legal to cast away const and mutate it. That is undefined behavior in D. A D compiler can assume, for example, that a const reference passed to a pure function will not mutate that reference, nor anything transitively referred to by that reference. No such assumption can be made like that in C++.
But that's meaningless though, because there's always the possibility that something somewhere else may have a non-const reference to that thing. Can you suggest a case where const could EVER be used in any sort of optimisation? I don't think const can possibly offer anything to the optimiser in any language, only type safety... I'd love to be wrong.
Apr 09 2013
next sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 07:52:20 UTC, Manu wrote:
 But that's meaningless though, because there's always the 
 possibility that
 something somewhere else may have a non-const reference to that 
 thing.
 Can you suggest a case where const could EVER be used in any 
 sort of
 optimisation?
 I don't think const can possibly offer anything to the 
 optimiser in any
 language, only type safety... I'd love to be wrong.
Don't forget, D variables are thread-local by default. If you get a const variable that is not shared or __gshared, compiler can safely assume that it will never change in this scope.
Apr 09 2013
parent reply Manu <turkeyman gmail.com> writes:
On 9 April 2013 17:54, Dicebot <m.strashun gmail.com> wrote:

 On Tuesday, 9 April 2013 at 07:52:20 UTC, Manu wrote:

 But that's meaningless though, because there's always the possibility that
 something somewhere else may have a non-const reference to that thing.
 Can you suggest a case where const could EVER be used in any sort of
 optimisation?
 I don't think const can possibly offer anything to the optimiser in any
 language, only type safety... I'd love to be wrong.
Don't forget, D variables are thread-local by default. If you get a const variable that is not shared or __gshared, compiler can safely assume that it will never change in this scope.
Errrm, only globals are shared by default. Locals or allocated memory are not thread-local, can be passed wherever they want, including other threads.
Apr 09 2013
next sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 08:00:38 UTC, Manu wrote:
 Errrm, only globals are shared by default.
 Locals or allocated memory are not thread-local, can be passed 
 wherever
 they want, including other threads.
No, globals are also thread-local by default. Everything is. And it was intended that all variables that are supposed to be shared by threads in any reference-based manner are marked by shared, so you can't get it without copying or casting shared away (undefined!). Well, have I mentioned that "shared" implementation is somewhat lacking in D now? :)
Apr 09 2013
parent reply Manu <turkeyman gmail.com> writes:
On 9 April 2013 18:03, Dicebot <m.strashun gmail.com> wrote:

 On Tuesday, 9 April 2013 at 08:00:38 UTC, Manu wrote:

 Errrm, only globals are shared by default.
 Locals or allocated memory are not thread-local, can be passed wherever
 they want, including other threads.
No, globals are also thread-local by default.
Sorry, that's what I meant, I typed the wrong thing >_< Everything is. Errrr, no? Only globals are thread-local. Everything else is either stack or heap allocated. And it was intended that all variables that are supposed to be shared by
 threads in any reference-based manner are marked by shared, so you can't
 get it without copying or casting shared away (undefined!).
Yes but that's ultimately useless. If sharing is undefined, and you can only use pass something to another thread via shared, then you basically can't use threads. shared is facilitated by blind casting. And codegen (which doesn't know if something actually WAS shared or not) can't be assuming it wasn't. I can't imagine a situation other than immutable where the compiler is able to presume __restrict in this way. Well, have I mentioned that "shared" implementation is somewhat lacking in
 D now? :)
It's almost a cruel joke. I try not to show that to people when I show them D ;)
Apr 09 2013
parent "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 08:31:06 UTC, Manu wrote:
 Errrr, no?
 Only globals are thread-local. Everything else is either stack 
 or heap
 allocated.
Well, stack is also thread-local, isn't it? ;) Heap objection accepted.
 Yes but that's ultimately useless. If sharing is undefined, and 
 you can
 only use pass something to another thread via shared, then you 
 basically
 can't use threads.
 shared is facilitated by blind casting. And codegen (which 
 doesn't know if
 something actually WAS shared or not) can't be assuming it 
 wasn't.
 I can't imagine a situation other than immutable where the 
 compiler is able
 to presume __restrict in this way.
My memories may be vague (I have been reading about it in a d-concurrency mail list used a looong time ago) but initial concept was quite elegant: everything that is intended to be shared should me marked with qualifiers. Function shall accepts shared parameters, do locks on them (which casts away shared in a library) and then use in regular functions. This clearly defines the distinction between functions that need to take care of synchronization and functions that can just work. I still think it is a clever concept, but without proper support in D/Phobos implementation is has become a cumbersome restriction. Once again, that is what my memory says, I'd like to be corrected by someone who has actually participated in that mail list.
Apr 09 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2013 1:00 AM, Manu wrote:
 Locals or allocated memory are not thread-local, can be passed wherever they
 want, including other threads.
Not unless they are marked as "shared".
Apr 10 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2013 12:52 AM, Manu wrote:
 But that's meaningless though, because there's always the possibility that
 something somewhere else may have a non-const reference to that thing.
 Can you suggest a case where const could EVER be used in any sort of
optimisation?
Sure: pure int bar(const int*); int foo(int* pt) { int t = *pt; // (1) int x = bar(&t); return t + // guaranteed to be same value as (1) x; } But the main purpose of const is so that you can have a single function that can operate on both mutable and immutable references. Otherwise, you'd have to do the copy/pasta two-step and write two functions.
Apr 10 2013
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2013 05:30 AM, Walter Bright wrote:
 On 4/8/2013 5:39 AM, Manu wrote:
 But D makes no further guarantee. I don't see how const in D is any
 different
 than const in C++ in that sense? That's basically the concept of
 const, it's not
 a useful concept for optimisation, only immutable is.
In C++, it is legal to cast away const and mutate it. That is undefined behavior in D. A D compiler can assume, for example, that a const reference passed to a pure function will not mutate that reference, nor anything transitively referred to by that reference. No such assumption can be made like that in C++.
The back end can assume this only if the DMD front end does its homework. It doesn't, probably because the spec does not formalize the type checking rules. There are plenty cases where a pure function can mutate something transitively referenced by some argument in safe code, even if all arguments are qualified const. eg. http://d.puremagic.com/issues/show_bug.cgi?id=9149
Apr 09 2013
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 9 April 2013 at 03:36:28 UTC, Walter Bright wrote:
 On 4/8/2013 5:39 AM, Manu wrote:
 But D makes no further guarantee. I don't see how const in D 
 is any different
 than const in C++ in that sense? That's basically the concept 
 of const, it's not
 a useful concept for optimisation, only immutable is.
In C++, it is legal to cast away const and mutate it. That is undefined behavior in D. A D compiler can assume, for example, that a const reference passed to a pure function will not mutate that reference, nor anything transitively referred to by that reference. No such assumption can be made like that in C++.
No, D have holes in its type system and so can't ensure anything. It has been show many many many times, especially by Timon and myself, and I'm kind of fed up to have to repeat that again and again, especiallt since fix proposal have recieved no attention at all. Stop claiming that such possibility exists, or take a serious look at how to really ensure it.
Apr 09 2013
next sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"deadalnix" <deadalnix gmail.com> wrote in message 
news:yhvwbephdechjxvrkyal forum.dlang.org...
 No, D have holes in its type system and so can't ensure anything. It has 
 been show many many many times, especially by Timon and myself, and I'm 
 kind of fed up to have to repeat that again and again, especiallt since 
 fix proposal have recieved no attention at all.

 Stop claiming that such possibility exists, or take a serious look at how 
 to really ensure it.
The const/pure etc systems are based on certain guarantees, and places where they can be broken are bugs. These bugs DO NOT change what optimization opportunities are allowed by the original guarantees. Stop claiming they do.
Apr 09 2013
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 9 April 2013 at 10:57:20 UTC, Daniel Murphy wrote:
 "deadalnix" <deadalnix gmail.com> wrote in message
 news:yhvwbephdechjxvrkyal forum.dlang.org...
 No, D have holes in its type system and so can't ensure 
 anything. It has been show many many many times, especially by 
 Timon and myself, and I'm kind of fed up to have to repeat 
 that again and again, especiallt since fix proposal have 
 recieved no attention at all.

 Stop claiming that such possibility exists, or take a serious 
 look at how to really ensure it.
The const/pure etc systems are based on certain guarantees, and places where they can be broken are bugs. These bugs DO NOT change what optimization opportunities are allowed by the original guarantees. Stop claiming they do.
Right now it isn't bugs as it is how thing are defined. And will be as long as no DIP solving this issue is accepted (at which point it will become a bug).
Apr 09 2013
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2013 12:57 PM, Daniel Murphy wrote:
 "deadalnix" <deadalnix gmail.com> wrote in message
 news:yhvwbephdechjxvrkyal forum.dlang.org...
 No, D have holes in its type system and so can't ensure anything. It has
 been show many many many times, especially by Timon and myself, and I'm
 kind of fed up to have to repeat that again and again, especiallt since
 fix proposal have recieved no attention at all.

 Stop claiming that such possibility exists, or take a serious look at how
 to really ensure it.
The const/pure etc systems are based on certain guarantees, and places where they can be broken are bugs. These bugs DO NOT change what optimization opportunities are allowed by the original guarantees. Stop claiming they do.
That is certainly true, but mostly so because basically the only thing that appears to be documented in the case of const are the guarantees themselves. In this case, it is pretty clear that a type system that actually ensures that the guarantees in the spec hold could be created, but I guess deadalnix dislikes the general scheme of: A: I have developed an algorithm that solves 3-SAT in linear time. B: It does not work. A: Please report this to the bug tracker. A: I have developed an algorithm that solves 3-SAT in linear time.
Apr 09 2013
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On 9 April 2013 20:57, Daniel Murphy <yebblies nospamgmail.com> wrote:

 "deadalnix" <deadalnix gmail.com> wrote in message
 news:yhvwbephdechjxvrkyal forum.dlang.org...
 No, D have holes in its type system and so can't ensure anything. It has
 been show many many many times, especially by Timon and myself, and I'm
 kind of fed up to have to repeat that again and again, especiallt since
 fix proposal have recieved no attention at all.

 Stop claiming that such possibility exists, or take a serious look at how
 to really ensure it.
The const/pure etc systems are based on certain guarantees, and places where they can be broken are bugs. These bugs DO NOT change what optimization opportunities are allowed by the original guarantees. Stop claiming they do.
The only optimisation possibility is for strong pure functions that are also nothrow, right? Was that the conditions for pure function refactoring?
Apr 09 2013
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2013 01:27 PM, Manu wrote:
 ...

 The only optimisation possibility is for strong pure functions that are
 also nothrow, right?  Was that the conditions for pure function refactoring?
No, strongly pure functions will always throw the same classes of exceptions when called with the same arguments. Therefore, with some flow-analysis, common subexpression elimination can apply to strongly pure functions which are not nothrow. Eg, given int foo(int)pure;, the transformation from a = foo(2); b = foo(2); to a = foo(2); b = a; is valid.
Apr 09 2013
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2013 01:39 PM, Timon Gehr wrote:
 On 04/09/2013 01:27 PM, Manu wrote:
 ...

 The only optimisation possibility is for strong pure functions that are
 also nothrow, right?  Was that the conditions for pure function
 refactoring?
No, strongly pure functions will always throw the same classes of exceptions when called with the same arguments. Therefore, with some flow-analysis, common subexpression elimination can apply to strongly pure functions which are not nothrow. Eg, given int foo(int)pure;,
and int a,b;,
 the transformation from

 a = foo(2);
 b = foo(2);

 to

 a = foo(2);
 b = a;

 is valid.
Apr 09 2013
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 9 April 2013 at 11:27:57 UTC, Manu wrote:
 The only optimisation possibility is for strong pure functions 
 that are
 also nothrow, right? Was that the conditions for pure function 
 refactoring?
No as no guarantee can exists as long as type qualifier transitivity isn't ensured.
Apr 09 2013
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/9/13 6:48 AM, deadalnix wrote:
 On Tuesday, 9 April 2013 at 03:36:28 UTC, Walter Bright wrote:
 On 4/8/2013 5:39 AM, Manu wrote:
 But D makes no further guarantee. I don't see how const in D is any
 different
 than const in C++ in that sense? That's basically the concept of
 const, it's not
 a useful concept for optimisation, only immutable is.
In C++, it is legal to cast away const and mutate it. That is undefined behavior in D. A D compiler can assume, for example, that a const reference passed to a pure function will not mutate that reference, nor anything transitively referred to by that reference. No such assumption can be made like that in C++.
No, D have holes in its type system and so can't ensure anything. It has been show many many many times, especially by Timon and myself, and I'm kind of fed up to have to repeat that again and again, especiallt since fix proposal have recieved no attention at all. Stop claiming that such possibility exists, or take a serious look at how to really ensure it.
Agreed. In parallel with work on improving quality, we also need to carefully address all holes in the type system. Andrei
Apr 09 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2013 3:48 AM, deadalnix wrote:
 No, D have holes in its type system and so can't ensure anything. It has been
 show many many many times, especially by Timon and myself, and I'm kind of fed
 up to have to repeat that again and again, especiallt since fix proposal have
 recieved no attention at all.

 Stop claiming that such possibility exists, or take a serious look at how to
 really ensure it.
Having a bug in the compiler doesn't mean the language design is full of holes.
Apr 10 2013
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/10/13 2:54 PM, Walter Bright wrote:
 On 4/9/2013 3:48 AM, deadalnix wrote:
 No, D have holes in its type system and so can't ensure anything. It
 has been
 show many many many times, especially by Timon and myself, and I'm
 kind of fed
 up to have to repeat that again and again, especiallt since fix
 proposal have
 recieved no attention at all.

 Stop claiming that such possibility exists, or take a serious look at
 how to
 really ensure it.
Having a bug in the compiler doesn't mean the language design is full of holes.
Unfortunately we have holes in the language definition, too. We can't afford to be glib about them. Andrei
Apr 10 2013
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/10/2013 08:54 PM, Walter Bright wrote:
 On 4/9/2013 3:48 AM, deadalnix wrote:
 No, D have holes in its type system and so can't ensure anything. It
 has been
 show many many many times, especially by Timon and myself, and I'm
 kind of fed
 up to have to repeat that again and again, especiallt since fix
 proposal have
 recieved no attention at all.

 Stop claiming that such possibility exists, or take a serious look at
 how to
 really ensure it.
Having a bug in the compiler doesn't mean the language design is full of holes.
Generally it does not, but is it actually not full of holes in this case? Can you give a short wrap-up of what the original language design is for type checking delegate context pointers? We can only guess, because it is not specified and much of what DMD does there is obviously buggy. In the end, we'll be left with three compiler front ends that implement three distinct competing designs.
Apr 10 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/10/2013 12:43 PM, Timon Gehr wrote:
 Generally it does not, but is it actually not full of holes in this case? Can
 you give a short wrap-up of what the original language design is for type
 checking delegate context pointers? We can only guess, because it is not
 specified and much of what DMD does there is obviously buggy. In the end, we'll
 be left with three compiler front ends that implement three distinct competing
 designs.
Clearly, delegates should not be able to break purity, const, shared, etc. Any setup that allows that is broken.
Apr 10 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/10/13 5:25 PM, Walter Bright wrote:
 On 4/10/2013 12:43 PM, Timon Gehr wrote:
 Generally it does not, but is it actually not full of holes in this
 case? Can
 you give a short wrap-up of what the original language design is for type
 checking delegate context pointers? We can only guess, because it is not
 specified and much of what DMD does there is obviously buggy. In the
 end, we'll
 be left with three compiler front ends that implement three distinct
 competing
 designs.
Clearly, delegates should not be able to break purity, const, shared, etc. Any setup that allows that is broken.
Yah, hence the holes :o). I think it's important to acknowledge that problems in the language definition exist and problems in the language implementation also exist. Both are important, but the former are more so because fixing them makes it possible to fix many of the implementation issues. Andrei
Apr 10 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/10/2013 2:28 PM, Andrei Alexandrescu wrote:
 On 4/10/13 5:25 PM, Walter Bright wrote:
 On 4/10/2013 12:43 PM, Timon Gehr wrote:
 Generally it does not, but is it actually not full of holes in this
 case? Can
 you give a short wrap-up of what the original language design is for type
 checking delegate context pointers? We can only guess, because it is not
 specified and much of what DMD does there is obviously buggy. In the
 end, we'll
 be left with three compiler front ends that implement three distinct
 competing
 designs.
Clearly, delegates should not be able to break purity, const, shared, etc. Any setup that allows that is broken.
Yah, hence the holes :o). I think it's important to acknowledge that problems in the language definition exist and problems in the language implementation also exist. Both are important, but the former are more so because fixing them makes it possible to fix many of the implementation issues.
My point was that competing designs are very probably not necessary. We just need to pull on the string on what must be.
Apr 10 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/10/2013 11:50 PM, Walter Bright wrote:
 ...

 My point was that competing designs are very probably not necessary. We
 just need to pull on the string on what must be.
Yes, IMO it is quite obvious how to do it. (transfer the meaning of the modifiers from member functions to local functions, disallow conversion to const for delegates and disallow loading a mutable delegate from a const receiver.) However, I think there are other opinions. There will probably always be as long as nothing is specified as the official behaviour.
Apr 10 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/10/2013 10:44 PM, Timon Gehr wrote:
 On 04/10/2013 11:50 PM, Walter Bright wrote:
 ...

 My point was that competing designs are very probably not necessary. We
 just need to pull on the string on what must be.
Yes, IMO it is quite obvious how to do it. (transfer the meaning of the modifiers from member functions to local functions, disallow conversion to const for delegates and disallow loading a mutable delegate from a const receiver.) However, I think there are other opinions. There will probably always be as long as nothing is specified as the official behaviour.
A delegate works exactly like a member function call. It has an implicit 'this' pointer, and how the 'this' pointer is qualified, just like for a member function, determines how it works.
Apr 10 2013
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/11/2013 07:48 AM, Walter Bright wrote:
 On 4/10/2013 10:44 PM, Timon Gehr wrote:
 On 04/10/2013 11:50 PM, Walter Bright wrote:
 ...

 My point was that competing designs are very probably not necessary. We
 just need to pull on the string on what must be.
Yes, IMO it is quite obvious how to do it. (transfer the meaning of the modifiers from member functions to local functions, disallow conversion to const for delegates and disallow loading a mutable delegate from a const receiver.) However, I think there are other opinions. There will probably always be as long as nothing is specified as the official behaviour.
A delegate works exactly like a member function call. It has an implicit 'this' pointer, and how the 'this' pointer is qualified, just like for a member function, determines how it works.
That's still not sufficient as a specification. A member function may be qualified differently from the 'this' pointer and calling said member function may even be disallowed because of this. For delegates, the same syntax element is used for qualifying the context pointer and the function. Therefore delegates and member functions need to behave differently.
Apr 11 2013
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 10 April 2013 at 18:54:15 UTC, Walter Bright wrote:
 On 4/9/2013 3:48 AM, deadalnix wrote:
 No, D have holes in its type system and so can't ensure 
 anything. It has been
 show many many many times, especially by Timon and myself, and 
 I'm kind of fed
 up to have to repeat that again and again, especiallt since 
 fix proposal have
 recieved no attention at all.

 Stop claiming that such possibility exists, or take a serious 
 look at how to
 really ensure it.
Having a bug in the compiler doesn't mean the language design is full of holes.
It is not about compiler bugs, it is about language definition. The issue has been explained over and over again, and DIP has been made about it already.
Apr 10 2013
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 8 April 2013 19:41, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 8 April 2013 10:06, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 04/08/2013 10:29 AM, Iain Buclaw wrote:

 On 6 April 2013 12:09, bearophile <bearophileHUGS lycos.com
 <mailto:bearophileHUGS lycos.**com <bearophileHUGS lycos.com>>> wrote:

     I remember Walter saying two or more times that the semantics of D
     offers some optimization opportunities that probably are not yet
     used to try to reduce the run-time of D programs. Is Walter willing
     to write down a list of such opportunities? (Ideas from other
     persons are welcome). Maybe some LDC/GDC developer will make the
     GCC/LLVM back-ends use them. The implementation of those ideas will
     require some time, so later it's better to put the list in the D
 wiki.

     Bye,
     bearophile



 This information could possibly be helpful.  Though given that most of
 (gdc) codegen is on par with g++, there's probably not much on the list
 that isn't already detected by the backend optimisation passes.


 --
 Iain Buclaw

 *(p < e ? p++ : p) = (c & 0x0f) + '0';
Does GDC use the additional type information for optimization? Eg. if something is immutable, then aliasing issues do not have to be considered for it when reading and writing through multiple pointers repeatedly.
It uses some type information, eg: const/immutable/wild -> qualified const. shared -> qualified volatile. shared + const/wild -> qualified const/volatile. Done nothing in regards to C 'restrict' optimisations. However the D array .ptr type could also be considered 'restrict' also.
Yes, I was just about to bring up __restrict, there is probably good opportunity for that. Why do you suppose .ptr is restrict? One problem with D's slicing is it's very hard to assume __restrict on basically any arrays. I feel like 'scope' might imply a __restrict input... although the relationship is kinda backwards, so maybe not... How about pure? Is GDC able to factor pure function calls with the same arguments outside of loops, or eliminate consecutive calls? It's really tedious to do this by hand, and breaks code continuity. Particularly important in a language that supports properties, since they'll be accessed consecutively all the time. What about immutable? You said it qualifies const, which in C++ is absolutely meaningless in terms of optimisation potential; just because something is const, the source of the pointer can certainly be non-const somewhere else, which means C++ can't possibly factor const loads outside of loops, and must respect consecutive dereferences of the same pointer. immutable in D should certainly be able to be factored outside loops, so it is more meaningful than const, and actually has real optimisation potential. Can GCC actually express an immutable value? I remember there was a problem a while back that I brought to you about GDC generating stack frames unnecessarily for leaf functions, is that resolved? I haven't checked in a while. Does GDC have access to a GDC-specific __restrict attribute to tag stuff manually? I'm struggling to think where it can be automated...
Apr 08 2013
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/08/2013 12:59 PM, Manu wrote:
 ...

 Does GDC have access to a GDC-specific __restrict attribute to tag stuff
 manually? I'm struggling to think where it can be automated...
As far as I can see, restrict can easily be applied to immutable data.
Apr 08 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
On 8 April 2013 20:59, Manu <turkeyman gmail.com> wrote:

 Does GDC have access to a GDC-specific __restrict attribute to tag stuff
 manually? I'm struggling to think where it can be automated...
I guess immutable is a subset of __restrict. It should definitely leverage at least 50% of __restrict's value to to mark immutable stuff as such.
Apr 08 2013
prev sibling next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 8 April 2013 11:59, Manu <turkeyman gmail.com> wrote:

 On 8 April 2013 19:41, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 8 April 2013 10:06, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 04/08/2013 10:29 AM, Iain Buclaw wrote:

 On 6 April 2013 12:09, bearophile <bearophileHUGS lycos.com
 <mailto:bearophileHUGS lycos.**com <bearophileHUGS lycos.com>>> wrote:

     I remember Walter saying two or more times that the semantics of D
     offers some optimization opportunities that probably are not yet
     used to try to reduce the run-time of D programs. Is Walter willing
     to write down a list of such opportunities? (Ideas from other
     persons are welcome). Maybe some LDC/GDC developer will make the
     GCC/LLVM back-ends use them. The implementation of those ideas will
     require some time, so later it's better to put the list in the D
 wiki.

     Bye,
     bearophile



 This information could possibly be helpful.  Though given that most of
 (gdc) codegen is on par with g++, there's probably not much on the list
 that isn't already detected by the backend optimisation passes.


 --
 Iain Buclaw

 *(p < e ? p++ : p) = (c & 0x0f) + '0';
Does GDC use the additional type information for optimization? Eg. if something is immutable, then aliasing issues do not have to be considered for it when reading and writing through multiple pointers repeatedly.
It uses some type information, eg: const/immutable/wild -> qualified const. shared -> qualified volatile. shared + const/wild -> qualified const/volatile. Done nothing in regards to C 'restrict' optimisations. However the D array .ptr type could also be considered 'restrict' also.
Yes, I was just about to bring up __restrict, there is probably good opportunity for that. Why do you suppose .ptr is restrict? One problem with D's slicing is it's very hard to assume __restrict on basically any arrays. I feel like 'scope' might imply a __restrict input... although the relationship is kinda backwards, so maybe not...
At least, many array operations, eg: a[] += b[]. Require the arrays not to be overlapping, so could do some optimisations based around that knowledge.
 How about pure? Is GDC able to factor pure function calls with the same
 arguments outside of loops, or eliminate consecutive calls? It's really
 tedious to do this by hand, and breaks code continuity. Particularly
 important in a language that supports properties, since they'll be accessed
 consecutively all the time.
Only builtins are pure in the sense of 'C'. Even functions considered PUREstrong by the frontend may update an internal state, so the rules just don't apply. Except for maybe global functions... In any case, the only benefit you can reap from 'D pure' functions are that they are more likely to be const-folded / inlined.
 What about immutable? You said it qualifies const, which in C++ is
 absolutely meaningless in terms of optimisation potential; just because
 something is const, the source of the pointer can certainly be non-const
 somewhere else, which means C++ can't possibly factor const loads outside
 of loops, and must respect consecutive dereferences of the same pointer.
 immutable in D should certainly be able to be factored outside loops, so
 it is more meaningful than const, and actually has real optimisation
 potential. Can GCC actually express an immutable value?
Other than saying that the type is const-qualified, the decl is set read-only, which only means to the backend that 'this decl may not be the lhs of an assignment.'
 I remember there was a problem a while back that I brought to you about
 GDC generating stack frames unnecessarily for leaf functions, is that
 resolved? I haven't checked in a while.
It probably is if you re referring to the thread I'm thinking of. Does GDC have access to a GDC-specific __restrict attribute to tag stuff
 manually? I'm struggling to think where it can be automated...
Nope, but that can be added in using our new attribute syntax. :~) Regards -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Apr 08 2013
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 8 April 2013 21:46, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 8 April 2013 11:59, Manu <turkeyman gmail.com> wrote:

 On 8 April 2013 19:41, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 8 April 2013 10:06, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 04/08/2013 10:29 AM, Iain Buclaw wrote:

 On 6 April 2013 12:09, bearophile <bearophileHUGS lycos.com
 <mailto:bearophileHUGS lycos.**com <bearophileHUGS lycos.com>>> wrote:

     I remember Walter saying two or more times that the semantics of D
     offers some optimization opportunities that probably are not yet
     used to try to reduce the run-time of D programs. Is Walter willing
     to write down a list of such opportunities? (Ideas from other
     persons are welcome). Maybe some LDC/GDC developer will make the
     GCC/LLVM back-ends use them. The implementation of those ideas will
     require some time, so later it's better to put the list in the D
 wiki.

     Bye,
     bearophile



 This information could possibly be helpful.  Though given that most of
 (gdc) codegen is on par with g++, there's probably not much on the list
 that isn't already detected by the backend optimisation passes.


 --
 Iain Buclaw

 *(p < e ? p++ : p) = (c & 0x0f) + '0';
Does GDC use the additional type information for optimization? Eg. if something is immutable, then aliasing issues do not have to be considered for it when reading and writing through multiple pointers repeatedly.
It uses some type information, eg: const/immutable/wild -> qualified const. shared -> qualified volatile. shared + const/wild -> qualified const/volatile. Done nothing in regards to C 'restrict' optimisations. However the D array .ptr type could also be considered 'restrict' also.
Yes, I was just about to bring up __restrict, there is probably good opportunity for that. Why do you suppose .ptr is restrict? One problem with D's slicing is it's very hard to assume __restrict on basically any arrays. I feel like 'scope' might imply a __restrict input... although the relationship is kinda backwards, so maybe not...
At least, many array operations, eg: a[] += b[]. Require the arrays not to be overlapping, so could do some optimisations based around that knowledge.
What reason is there that these may not be overlapping?
 How about pure? Is GDC able to factor pure function calls with the same
 arguments outside of loops, or eliminate consecutive calls? It's really
 tedious to do this by hand, and breaks code continuity. Particularly
 important in a language that supports properties, since they'll be accessed
 consecutively all the time.
Only builtins are pure in the sense of 'C'. Even functions considered PUREstrong by the frontend may update an internal state, so the rules just don't apply. Except for maybe global functions... In any case, the only benefit you can reap from 'D pure' functions are that they are more likely to be const-folded / inlined.
Oh my god... ..... this is the most upsetting thing I've heard all day! :( No really, I have been SOOOO excited for so long about this optimisation potential in D! There's gotta be something that can be done! >_< Does the front end know if the function actually DOES assign to any state? The compiler could easily work that out, and in the event it doesn't actually perform any such assignment, it could be marked pure for reals... What about immutable? You said it qualifies const, which in C++ is
 absolutely meaningless in terms of optimisation potential; just because
 something is const, the source of the pointer can certainly be non-const
 somewhere else, which means C++ can't possibly factor const loads outside
 of loops, and must respect consecutive dereferences of the same pointer.
 immutable in D should certainly be able to be factored outside loops, so
 it is more meaningful than const, and actually has real optimisation
 potential. Can GCC actually express an immutable value?
Other than saying that the type is const-qualified, the decl is set read-only, which only means to the backend that 'this decl may not be the lhs of an assignment.'
Well tell the backend that it's restrict aswell, that will give the backend more opportunities where aliasing is a potential problem.
 I remember there was a problem a while back that I brought to you about
 GDC generating stack frames unnecessarily for leaf functions, is that
 resolved? I haven't checked in a while.
It probably is if you re referring to the thread I'm thinking of. Does GDC have access to a GDC-specific __restrict attribute to tag stuff
 manually? I'm struggling to think where it can be automated...
Nope, but that can be added in using our new attribute syntax. :~)
So, the sad truth is, with all of D's numerous keywords and explicit qualifications, there are actually NO potential optimisations available that C could not equally make use of. I can't believe that pure thing, that's seriously depressing! I forgot you could assign to state within pure functions. Why is that? It's not actually pure at all! I guess there's a little bonus if you tag immutable as restrict, but that's a disappointing sum total...
Apr 08 2013
next sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Monday, 8 April 2013 at 12:37:48 UTC, Manu wrote:
 On 8 April 2013 21:46, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 Only builtins are pure in the sense of 'C'.  Even functions 
 considered
 PUREstrong by the frontend may update an internal state, so 
 the rules just
 don't apply.  Except for maybe global functions...   In any 
 case, the only
 benefit you can reap from 'D pure' functions are that they are 
 more likely
 to be const-folded / inlined.
Oh my god... ..... this is the most upsetting thing I've heard all day! :( No really, I have been SOOOO excited for so long about this optimisation potential in D! There's gotta be something that can be done! >_< Does the front end know if the function actually DOES assign to any state? The compiler could easily work that out, and in the event it doesn't actually perform any such assignment, it could be marked pure for reals...
Iain, are you sure about that? (No offense, but you have been wrong about what GCC can/can't do in the past. :P) Could you maybe elaborate a bit and present a counterexample? It might also be a question of how the »as-if« rule is really defined for pure function calls. In any case, if the source is available, the LLVM optimizer is usually very good at figuring out »pure for reals« (inferring the LLVM 'readnone' attribute). Obviously, this doesn't help you when you are doing separate compilation, though. David
Apr 08 2013
next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 8 April 2013 at 13:32:36 UTC, David Nadlinger wrote:
 On Monday, 8 April 2013 at 12:37:48 UTC, Manu wrote:
 On 8 April 2013 21:46, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 Only builtins are pure in the sense of 'C'.  Even functions 
 considered
 PUREstrong by the frontend may update an internal state, so 
 the rules just
 don't apply. […]
Iain, are you sure about that?
(you also need nothrow, of course) David
Apr 08 2013
prev sibling next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 8 April 2013 14:32, David Nadlinger <see klickverbot.at> wrote:

 On Monday, 8 April 2013 at 12:37:48 UTC, Manu wrote:

 On 8 April 2013 21:46, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 Only builtins are pure in the sense of 'C'.  Even functions considered
 PUREstrong by the frontend may update an internal state, so the rules
 just
 don't apply.  Except for maybe global functions...   In any case, the
 only
 benefit you can reap from 'D pure' functions are that they are more
 likely
 to be const-folded / inlined.
Oh my god... ..... this is the most upsetting thing I've heard all day! =
:(
 No really, I have been SOOOO excited for so long about this optimisation
 potential in D!
 There's gotta be something that can be done! >_<

 Does the front end know if the function actually DOES assign to any stat=
e?
 The compiler could easily work that out, and in the event it doesn't
 actually perform any such assignment, it could be marked pure for reals.=
..

 Iain, are you sure about that? (No offense, but you have been wrong about
 what GCC can/can't do in the past. :P) Could you maybe elaborate a bit an=
d
 present a counterexample? It might also be a question of how the =BBas-if=
=AB
 rule is really defined for pure function calls.

 In any case, if the source is available, the LLVM optimizer is usually
 very good at figuring out =BBpure for reals=AB (inferring the LLVM 'readn=
one'
 attribute). Obviously, this doesn't help you when you are doing separate
 compilation, though.

 David
Sure about what? I don't even know what you are talking about. :o) <sic> --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
Apr 08 2013
prev sibling parent Johannes Pfau <nospam example.com> writes:
Am Mon, 08 Apr 2013 15:32:35 +0200
schrieb "David Nadlinger" <see klickverbot.at>:

 On Monday, 8 April 2013 at 12:37:48 UTC, Manu wrote:
 On 8 April 2013 21:46, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 Only builtins are pure in the sense of 'C'.  Even functions=20
 considered
 PUREstrong by the frontend may update an internal state, so=20
 the rules just
 don't apply.  Except for maybe global functions...   In any=20
 case, the only
 benefit you can reap from 'D pure' functions are that they are=20
 more likely
 to be const-folded / inlined.
Oh my god... ..... this is the most upsetting thing I've heard=20 all day! :( No really, I have been SOOOO excited for so long about this=20 optimisation potential in D! There's gotta be something that can be done! >_< Does the front end know if the function actually DOES assign to=20 any state? The compiler could easily work that out, and in the event it=20 doesn't actually perform any such assignment, it could be marked pure=20 for reals...
=20 Iain, are you sure about that? (No offense, but you have been=20 wrong about what GCC can/can't do in the past. :P) Could you=20 maybe elaborate a bit and present a counterexample? It might also=20 be a question of how the =C2=BBas-if=C2=AB rule is really defined for pur=
e=20
 function calls.
=20
 In any case, if the source is available, the LLVM optimizer is=20
 usually very good at figuring out =C2=BBpure for reals=C2=AB (inferring t=
he=20
 LLVM 'readnone' attribute). Obviously, this doesn't help you when=20
 you are doing separate compilation, though.
=20
 David
I guess he only meant that the pure attribute doesn't help much, especially when compared to the GCC __pure__ C attribute. Of course the backend might still figure out that a function is really pure if the source code is known, but that probably also applies to functions not marked as pure so there's not much benefit for the backend if a function is marked pure or not.
Apr 08 2013
prev sibling next sibling parent reply Johannes Pfau <nospam example.com> writes:
Am Mon, 8 Apr 2013 22:37:33 +1000
schrieb Manu <turkeyman gmail.com>:


 Only builtins are pure in the sense of 'C'.  Even functions
 considered PUREstrong by the frontend may update an internal state,
 so the rules just don't apply.  Except for maybe global
 functions...   In any case, the only benefit you can reap from 'D
 pure' functions are that they are more likely to be const-folded /
 inlined.
Oh my god... ..... this is the most upsetting thing I've heard all day! :( No really, I have been SOOOO excited for so long about this optimisation potential in D! There's gotta be something that can be done! >_<
And to make it even worse AFAICT D's nothrow is also meaningless for optimization. As you can still throw errors/throwables the backend gains nothing from nothrow. It still has to analyze a function to know if it is actually __NOTHROW__ in the gcc sense. I think there was at least one gdc bug related to this which only showed on ARM, but I'd have to check that again. http://bugzilla.gdcproject.org/show_bug.cgi?id=10 (Though admittedly I'm not sure if there's any optimization potential with nothrow)
Apr 08 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/8/2013 11:20 AM, Johannes Pfau wrote:
 (Though admittedly I'm not sure if there's any optimization potential
 with nothrow)
There is. The setting up of the exception handling frames can be omitted, and eh frames prevent enregistering of many variables.
Apr 08 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/8/2013 5:37 AM, Manu wrote:
     Only builtins are pure in the sense of 'C'.  Even functions considered
     PUREstrong by the frontend may update an internal state, so the rules just
     don't apply.  Except for maybe global functions...   In any case, the only
     benefit you can reap from 'D pure' functions are that they are more likely
     to be const-folded / inlined.

 Oh my god... ..... this is the most upsetting thing I've heard all day! :(
 No really, I have been SOOOO excited for so long about this optimisation
 potential in D!
 There's gotta be something that can be done! >_<
I believe Iain is incorrect. Pure functions cannot squirrel away any persistent state.
Apr 08 2013
parent reply Manu <turkeyman gmail.com> writes:
On 9 April 2013 14:39, Walter Bright <newshound2 digitalmars.com> wrote:

 On 4/8/2013 5:37 AM, Manu wrote:

     Only builtins are pure in the sense of 'C'.  Even functions considered
     PUREstrong by the frontend may update an internal state, so the rules
 just
     don't apply.  Except for maybe global functions...   In any case, the
 only
     benefit you can reap from 'D pure' functions are that they are more
 likely
     to be const-folded / inlined.

 Oh my god... ..... this is the most upsetting thing I've heard all day! :(
 No really, I have been SOOOO excited for so long about this optimisation
 potential in D!
 There's gotta be something that can be done! >_<
I believe Iain is incorrect. Pure functions cannot squirrel away any persistent state.
Are you saying the example above is not actually valid code? struct Foo { int a = 0; pure int bar( int n ) { // Weakly pure a += n; return a; } } That's not pure. Call it twice with the same args, you'll different answers. How can that possibly be considered pure in any sense? And it's useless in terms of optimisation, so why bother at all? What does it offer?
Apr 09 2013
next sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 07:57:37 UTC, Manu wrote:
 Are you saying the example above is not actually valid code?

 struct Foo {
     int a = 0;
     pure int bar( int n ) { // Weakly pure
         a += n;
         return a;
     }
 }

 That's not pure. Call it twice with the same args, you'll 
 different
 answers. How can that possibly be considered pure in any sense?
 And it's useless in terms of optimisation, so why bother at 
 all? What does
 it offer?
It is valid code. It is "weak pure". "pure' keyword means both "strong pure" or "weak pure" depending on function body. Crap.
Apr 09 2013
next sibling parent reply Manu <turkeyman gmail.com> writes:
On 9 April 2013 18:04, Dicebot <m.strashun gmail.com> wrote:

 On Tuesday, 9 April 2013 at 07:57:37 UTC, Manu wrote:

 Are you saying the example above is not actually valid code?

 struct Foo {
     int a = 0;
     pure int bar( int n ) { // Weakly pure
         a += n;
         return a;
     }
 }

 That's not pure. Call it twice with the same args, you'll different
 answers. How can that possibly be considered pure in any sense?
 And it's useless in terms of optimisation, so why bother at all? What does
 it offer?
It is valid code. It is "weak pure". "pure' keyword means both "strong pure" or "weak pure" depending on function body. Crap.
How can 'weak pure' reasonably be called any kind of 'pure'? It's not pure at all. The function returns a completely different result when called twice. That's the definition of not-pure. I suggest that no D language newbie would ever reasonably expect that behaviour.
Apr 09 2013
next sibling parent "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 08:33:53 UTC, Manu wrote:
 How can 'weak pure' reasonably be called any kind of 'pure'? 
 It's not pure
 at all. The function returns a completely different result when 
 called
 twice. That's the definition of not-pure.
 I suggest that no D language newbie would ever reasonably 
 expect that
 behaviour.
It is "weak pure" because it can be called by "strong pure" functions without violating "strong pure" guarantees (not-pure-at-all functions can't). It is confusing indeed and I remember some questions on StackOverflow on topic. I think having separate keywords/attributes would have helped.
Apr 09 2013
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2013 10:33 AM, Manu wrote:
 ...

 How can 'weak pure' reasonably be called any kind of 'pure'? It's not
 pure at all. The function returns a completely different result when
 called twice. That's the definition of not-pure.
(Actually this is not the definition of impure.) In D, 'pure' forbids reading or writing of mutable static variables.
 I suggest that no D language newbie would ever reasonably expect that
 behaviour.
Sure. Many keyword choices in D are unhelpful for newbies, or technically wrong. enum -> const catch -> handle do -> repeat for -> (no suggestion) const -> readonly inout -> (no suggestion) lazy -> byname pure -> (no suggestion) static -> (no suggestion) struct -> (no suggestion) throw -> raise / signal union -> (no suggestion)
Apr 09 2013
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-04-09 12:24, Timon Gehr wrote:

 static -> (no suggestion)
"static" has quite a lot of overloads as well. -- /Jacob Carlborg
Apr 09 2013
prev sibling parent "ixid" <nuaccount gmail.com> writes:
On Tuesday, 9 April 2013 at 10:24:45 UTC, Timon Gehr wrote:
 On 04/09/2013 10:33 AM, Manu wrote:
 ...

 How can 'weak pure' reasonably be called any kind of 'pure'? 
 It's not
 pure at all. The function returns a completely different 
 result when
 called twice. That's the definition of not-pure.
(Actually this is not the definition of impure.) In D, 'pure' forbids reading or writing of mutable static variables.
 I suggest that no D language newbie would ever reasonably 
 expect that
 behaviour.
Sure. Many keyword choices in D are unhelpful for newbies, or technically wrong. enum -> const catch -> handle do -> repeat for -> (no suggestion) const -> readonly inout -> (no suggestion) lazy -> byname pure -> (no suggestion) static -> (no suggestion) struct -> (no suggestion) throw -> raise / signal union -> (no suggestion)
for -> loop?
Apr 09 2013
prev sibling next sibling parent reply "tn" <no email.com> writes:
On Tuesday, 9 April 2013 at 08:33:53 UTC, Manu wrote:
 On 9 April 2013 18:04, Dicebot <m.strashun gmail.com> wrote:

 On Tuesday, 9 April 2013 at 07:57:37 UTC, Manu wrote:

 Are you saying the example above is not actually valid code?

 struct Foo {
     int a = 0;
     pure int bar( int n ) { // Weakly pure
         a += n;
         return a;
     }
 }

 That's not pure. Call it twice with the same args, you'll 
 different
 answers. How can that possibly be considered pure in any 
 sense?
 And it's useless in terms of optimisation, so why bother at 
 all? What does
 it offer?
It is valid code. It is "weak pure". "pure' keyword means both "strong pure" or "weak pure" depending on function body. Crap.
How can 'weak pure' reasonably be called any kind of 'pure'? It's not pure at all. The function returns a completely different result when called twice.
The returned results are different because the parameters you are calling it with are different. Note that for member functions 'this' is also passed implicitly as a ref parameter. On the second call it has different value than on the first call. If you don't want to allow mutating 'this' you should make the function const, thus making the implicit 'this' parameter const ref.
Apr 09 2013
parent Manu <turkeyman gmail.com> writes:
On 9 April 2013 21:30, tn <no email.com> wrote:

 On Tuesday, 9 April 2013 at 08:33:53 UTC, Manu wrote:

 On 9 April 2013 18:04, Dicebot <m.strashun gmail.com> wrote:

  On Tuesday, 9 April 2013 at 07:57:37 UTC, Manu wrote:
  Are you saying the example above is not actually valid code?
 struct Foo {
     int a = 0;
     pure int bar( int n ) { // Weakly pure
         a += n;
         return a;
     }
 }

 That's not pure. Call it twice with the same args, you'll different
 answers. How can that possibly be considered pure in any sense?
 And it's useless in terms of optimisation, so why bother at all? What
 does
 it offer?
It is valid code. It is "weak pure". "pure' keyword means both "strong pure" or "weak pure" depending on function body. Crap.
How can 'weak pure' reasonably be called any kind of 'pure'? It's not pure at all. The function returns a completely different result when called twice.
The returned results are different because the parameters you are calling it with are different. Note that for member functions 'this' is also passed implicitly as a ref parameter. On the second call it has different value than on the first call. If you don't want to allow mutating 'this' you should make the function const, thus making the implicit 'this' parameter const ref.
Ah, yes. Good point. I don't know how I missed that point prior! Okay sir, I buy your argument! :)
Apr 09 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2013 1:33 AM, Manu wrote:
 How can 'weak pure' reasonably be called any kind of 'pure'? It's not pure at
 all. The function returns a completely different result when called twice.
 That's the definition of not-pure.
 I suggest that no D language newbie would ever reasonably expect that
behaviour.
I explained it in another reply here. I agree that it is initially confusing. I was myself confused about it until Don set me straight!
Apr 10 2013
parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Wednesday, 10 April 2013 at 18:24:22 UTC, Walter Bright wrote:
 On 4/9/2013 1:33 AM, Manu wrote:
 How can 'weak pure' reasonably be called any kind of 'pure'? 
 It's not pure at
 all. The function returns a completely different result when 
 called twice.
 That's the definition of not-pure.
 I suggest that no D language newbie would ever reasonably 
 expect that behaviour.
I explained it in another reply here. I agree that it is initially confusing. I was myself confused about it until Don set me straight!
For some reason I was never confused by this issue, even though I'm clearly in the minority. I always thought 'pure' set up an isolated set of instructions which only behaved according to what it was given. So if I found out it could modify by reference, it didn't shake my basic idea of what it was supposed to do. As long as it modified in exactly the same way, it still seemed like a separate and predictable box.
Apr 10 2013
prev sibling next sibling parent reply =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Tue, 09 Apr 2013 10:33:45 +0200, Manu <turkeyman gmail.com> wrote:

 On 9 April 2013 18:04, Dicebot <m.strashun gmail.com> wrote:

 On Tuesday, 9 April 2013 at 07:57:37 UTC, Manu wrote:

 Are you saying the example above is not actually valid code?

 struct Foo {
     int a = 0;
     pure int bar( int n ) { // Weakly pure
         a += n;
         return a;
     }
 }

 That's not pure. Call it twice with the same args, you'll different
 answers. How can that possibly be considered pure in any sense?
 And it's useless in terms of optimisation, so why bother at all? What  
 does
 it offer?
It is valid code. It is "weak pure". "pure' keyword means both "strong pure" or "weak pure" depending on function body. Crap.
How can 'weak pure' reasonably be called any kind of 'pure'?
It's pure in the sense that it can be used inside (strongly) pure functions.
 I suggest that no D language newbie would ever reasonably expect that
 behaviour.
And with that, I absolutely have to agree. -- Simen
Apr 09 2013
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/9/13 4:43 AM, Simen Kjærås wrote:
 On Tue, 09 Apr 2013 10:33:45 +0200, Manu <turkeyman gmail.com> wrote:
 I suggest that no D language newbie would ever reasonably expect that
 behaviour.
And with that, I absolutely have to agree.
Me too. But then any innovation by definition has an element of surprise. Andrei
Apr 09 2013
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/9/13 4:04 AM, Dicebot wrote:
 On Tuesday, 9 April 2013 at 07:57:37 UTC, Manu wrote:
 Are you saying the example above is not actually valid code?

 struct Foo {
 int a = 0;
 pure int bar( int n ) { // Weakly pure
 a += n;
 return a;
 }
 }

 That's not pure. Call it twice with the same args, you'll different
 answers. How can that possibly be considered pure in any sense?
 And it's useless in terms of optimisation, so why bother at all? What
 does
 it offer?
It is valid code. It is "weak pure". "pure' keyword means both "strong pure" or "weak pure" depending on function body. Crap.
s/body/signature/ s/Crap/Awesome/ Andrei
Apr 09 2013
next sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 12:56:04 UTC, Andrei Alexandrescu 
wrote:
 It is valid code. It is "weak pure". "pure' keyword means both
 "strong pure" or "weak pure" depending on function body. Crap.
s/body/signature/ s/Crap/Awesome/
Not gonna argue latter but former is just wrong. struct Test { int a; pure int foo1() // strong pure { return 42; } pure int foo2() // weak pure { return a++; } } Signature is the same for both functions.
Apr 09 2013
next sibling parent reply "Pelle =?UTF-8?B?TcOlbnNzb24i?= <pelle.mansson.ok gmail.com> writes:
On Tuesday, 9 April 2013 at 13:49:12 UTC, Dicebot wrote:
 On Tuesday, 9 April 2013 at 12:56:04 UTC, Andrei Alexandrescu 
 wrote:
 It is valid code. It is "weak pure". "pure' keyword means both
 "strong pure" or "weak pure" depending on function body. Crap.
s/body/signature/ s/Crap/Awesome/
Not gonna argue latter but former is just wrong. struct Test { int a; pure int foo1() // strong pure { return 42; } pure int foo2() // weak pure { return a++; } } Signature is the same for both functions.
Think of all your member functions as non-member functions taking the object as a ref parameter. pure int foo1(ref Test this) { return 42; } shouldn't be strongly pure (as it can access mutable non local state).
Apr 09 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 14:06:31 UTC, Pelle Månsson wrote:
 shouldn't be strongly pure (as it can access mutable non local 
 state).
I was under impression that pure is about verifying what function actually does, not what it probably can.
Apr 09 2013
parent reply =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Tue, 09 Apr 2013 16:15:40 +0200, Dicebot <m.strashun gmail.com> wrote=
:

 On Tuesday, 9 April 2013 at 14:06:31 UTC, Pelle M=C3=A5nsson wrote:
 shouldn't be strongly pure (as it can access mutable non local state)=
.
 I was under impression that pure is about verifying what function  =
 actually does, not what it probably can.
It's based purely on function signature, so we're dealing with possibles= in many cases. -- = Simen
Apr 09 2013
next sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 14:50:58 UTC, Simen Kjærås wrote:
 On Tue, 09 Apr 2013 16:15:40 +0200, Dicebot 
 <m.strashun gmail.com> wrote:

 On Tuesday, 9 April 2013 at 14:06:31 UTC, Pelle Månsson wrote:
 shouldn't be strongly pure (as it can access mutable non 
 local state).
I was under impression that pure is about verifying what function actually does, not what it probably can.
It's based purely on function signature, so we're dealing with possibles in many cases.
You got me lost here again. Definition of pure in dlang.org says: "To that end, a pure function: * does not read or write any global or static mutable state * cannot call functions that are not pure * can override an impure function, but an impure function cannot override a pure one * is covariant with an impure function * cannot perform I/O" It is all about behavior, not function signature. And function that takes ref parameter and does not read/write it is pure by this list.
Apr 09 2013
parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On 2013-04-09, 17:11, Dicebot wrote:

 On Tuesday, 9 April 2013 at 14:50:58 UTC, Simen Kj=C3=A6r=C3=A5s wrote=
:
 On Tue, 09 Apr 2013 16:15:40 +0200, Dicebot <m.strashun gmail.com>  =
 wrote:

 On Tuesday, 9 April 2013 at 14:06:31 UTC, Pelle M=C3=A5nsson wrote:
 shouldn't be strongly pure (as it can access mutable non local stat=
e).
 I was under impression that pure is about verifying what function  =
 actually does, not what it probably can.
It's based purely on function signature, so we're dealing with possib=
les
 in many cases.
You got me lost here again. Definition of pure in dlang.org says: "To =
=
 that end, a pure function:

 * does not read or write any global or static mutable state
 * cannot call functions that are not pure
 * can override an impure function, but an impure function cannot  =
 override a pure one
 * is covariant with an impure function
 * cannot perform I/O"

 It is all about behavior, not function signature. And function that  =
 takes ref parameter and does not read/write it is pure by this list.
Indeed. The definition should be updated then, because it's the signatur= e that counts. Consider: int[] foo(int* p) pure; Given only this prototype, we can know that the function is weakly pure.= If a function body was required, we would know nothing more, are we to assume it is strongly pure because no mutation is evident? Of course we are not. In the same way, because D supports 'header' files= (files with implementation stripped out), the function signature must convey all the necessary information to say if a function is strongly pure or not. -- = Simen
Apr 09 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2013 7:50 AM, Simen Kjærås wrote:
 It's based purely on function signature
Correct. (I should point out that there are cases where the compiler infers purity from the function body: 1. lambdas 2. template functions 3. auto functions )
Apr 10 2013
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
2013/4/9 Dicebot <m.strashun gmail.com>

 On Tuesday, 9 April 2013 at 12:56:04 UTC, Andrei Alexandrescu wrote:

 It is valid code. It is "weak pure". "pure' keyword means both
 "strong pure" or "weak pure" depending on function body. Crap.
s/body/signature/ s/Crap/Awesome/
Not gonna argue latter but former is just wrong. struct Test { int a; pure int foo1() // strong pure { return 42; } pure int foo2() // weak pure { return a++; } } Signature is the same for both functions.
Both have weak pure. Purity is always calculated only from the function signature. If you make member function "strong pure", _at least_ it should be qualified with "immutable". pure int foo3() immutable // strong pure { return 10; } Kenji Hara
Apr 09 2013
prev sibling next sibling parent reply "Jesse Phillips" <Jessekphillips+d gmail.com> writes:
On Tuesday, 9 April 2013 at 13:49:12 UTC, Dicebot wrote:
 struct Test
 {
     int a;
     pure int foo1() // strong pure
     {
         return 42;
     }

     pure int foo2() // weak pure
     {
         return a++;
     }
 }
Isn't it pure int foo1() const // strong pure
Apr 09 2013
parent reply =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Tue, 09 Apr 2013 16:09:40 +0200, Jesse Phillips  
<Jessekphillips+d gmail.com> wrote:

 On Tuesday, 9 April 2013 at 13:49:12 UTC, Dicebot wrote:
 struct Test
 {
     int a;
     pure int foo1() // strong pure
     {
         return 42;
     }

     pure int foo2() // weak pure
     {
         return a++;
     }
 }
Isn't it pure int foo1() const // strong pure
const is not sufficient, as someone else might have a mutable reference. immutable is needed. -- Simen
Apr 09 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2013 7:12 AM, Simen Kjærås wrote:
 const is not sufficient, as someone else might have a mutable
 reference. immutable is needed.
const is sufficient for strongly pure, because another reference is not available to the function body, and so the function cannot mutate it.
Apr 10 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 10 April 2013 at 18:33:26 UTC, Walter Bright wrote:
 On 4/9/2013 7:12 AM, Simen Kjærås wrote:
 const is not sufficient, as someone else might have a mutable
 reference. immutable is needed.
const is sufficient for strongly pure, because another reference is not available to the function body, and so the function cannot mutate it.
No ! A delegate reached via parameters and called can mute them. call with const parameter can be considered strongly pure if the argument is immutable (granted we fix delegate transitivity issues).
Apr 10 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/10/2013 5:33 PM, deadalnix wrote:
 call with const parameter can be considered strongly pure if the argument is
 immutable
The argument doesn't need to be immutable because nobody can change it while the function is running.
Apr 10 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/11/2013 02:41 AM, Walter Bright wrote:
 On 4/10/2013 5:33 PM, deadalnix wrote:
 call with const parameter can be considered strongly pure if the
 argument is
 immutable
The argument doesn't need to be immutable because nobody can change it while the function is running.
(He has written DIP30. Under DIP30 this would no longer be the case.)
Apr 10 2013
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 11 April 2013 at 00:41:01 UTC, Walter Bright wrote:
 On 4/10/2013 5:33 PM, deadalnix wrote:
 call with const parameter can be considered strongly pure if 
 the argument is
 immutable
The argument doesn't need to be immutable because nobody can change it while the function is running.
I explained the sentence just above how it is possible. Ignoring issue rarely help when it come to solve them.
Apr 11 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/11/2013 3:02 AM, deadalnix wrote:
 On Thursday, 11 April 2013 at 00:41:01 UTC, Walter Bright wrote:
 On 4/10/2013 5:33 PM, deadalnix wrote:
 call with const parameter can be considered strongly pure if the argument is
 immutable
The argument doesn't need to be immutable because nobody can change it while the function is running.
I explained the sentence just above how it is possible. Ignoring issue rarely help when it come to solve them.
The delegate issue is a known one, and can be solved, and is not relevant to this point.
Apr 11 2013
parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 11 April 2013 at 17:52:43 UTC, Walter Bright wrote:
 On 4/11/2013 3:02 AM, deadalnix wrote:
 On Thursday, 11 April 2013 at 00:41:01 UTC, Walter Bright 
 wrote:
 On 4/10/2013 5:33 PM, deadalnix wrote:
 call with const parameter can be considered strongly pure if 
 the argument is
 immutable
The argument doesn't need to be immutable because nobody can change it while the function is running.
I explained the sentence just above how it is possible. Ignoring issue rarely help when it come to solve them.
The delegate issue is a known one, and can be solved, and is not relevant to this point.
See Timon's post. Both are deeply linked.
Apr 11 2013
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/9/13 9:49 AM, Dicebot wrote:
 On Tuesday, 9 April 2013 at 12:56:04 UTC, Andrei Alexandrescu wrote:
 It is valid code. It is "weak pure". "pure' keyword means both
 "strong pure" or "weak pure" depending on function body. Crap.
s/body/signature/ s/Crap/Awesome/
Not gonna argue latter but former is just wrong. struct Test { int a; pure int foo1() // strong pure { return 42; } pure int foo2() // weak pure { return a++; } } Signature is the same for both functions.
Both are weakly pure. Andrei
Apr 09 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 15:20:48 UTC, Andrei Alexandrescu 
wrote:
 Not gonna argue latter but former is just wrong.

 struct Test
 {
 int a;
 pure int foo1() // strong pure
 {
 return 42;
 }

 pure int foo2() // weak pure
 {
 return a++;
 }
 }

 Signature is the same for both functions.
Both are weakly pure. Andrei
And that is even more surprising as foo2 perfectly matches concept of pure and can be applied all possible optimizations to. It is weird. "weak pure" is useful only to implement "strong pure". "strong pure" is useful only if it can be statically enforced to provide some guarantees. "strong pure" is useless because it shares same annotation with "weak pure".
Apr 09 2013
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 9 April 2013 at 15:42:38 UTC, Dicebot wrote:
 On Tuesday, 9 April 2013 at 15:20:48 UTC, Andrei Alexandrescu 
 wrote:
 Not gonna argue latter but former is just wrong.

 struct Test
 {
 int a;
 pure int foo1() // strong pure
 {
 return 42;
 }

 pure int foo2() // weak pure
 {
 return a++;
 }
 }

 Signature is the same for both functions.
Both are weakly pure. Andrei
And that is even more surprising as foo2 perfectly matches concept of pure
Don't you mean foo1? I have no idea what i'm talking about but foo1 looks a lot more pure than foo2 to me.
Apr 09 2013
parent "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 15:52:36 UTC, John Colvin wrote:
 Don't you mean foo1? I have no idea what i'm talking about but 
 foo1 looks a lot more pure than foo2 to me.
foo1, of course, beg my pardon.
Apr 09 2013
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/9/13 11:42 AM, Dicebot wrote:
 On Tuesday, 9 April 2013 at 15:20:48 UTC, Andrei Alexandrescu wrote:
 Not gonna argue latter but former is just wrong.

 struct Test
 {
 int a;
 pure int foo1() // strong pure
 {
 return 42;
 }

 pure int foo2() // weak pure
 {
 return a++;
 }
 }

 Signature is the same for both functions.
Both are weakly pure. Andrei
And that is even more surprising as foo2 perfectly matches concept of pure and can be applied all possible optimizations to. It is weird.
I disagree about it being weird.
 "weak pure" is useful only to implement "strong pure". "strong pure" is
 useful only if it can be statically enforced to provide some guarantees.
 "strong pure" is useless because it shares same annotation with "weak
 pure".
I think it's a great design, very useful and innovative. Andrei
Apr 09 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 16:15:38 UTC, Andrei Alexandrescu 
wrote:
 "weak pure" is useful only to implement "strong pure". "strong 
 pure" is
 useful only if it can be statically enforced to provide some 
 guarantees.
 "strong pure" is useless because it shares same annotation 
 with "weak
 pure".
I think it's a great design, very useful and innovative.
Agree on it being great and innovative. But I fail to see usefulness with current design. Can you provide examples how current pure design allows for better code / optimizations?
Apr 09 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 9 April 2013 at 17:39:47 UTC, Dicebot wrote:
 On Tuesday, 9 April 2013 at 16:15:38 UTC, Andrei Alexandrescu 
 wrote:
 "weak pure" is useful only to implement "strong pure". 
 "strong pure" is
 useful only if it can be statically enforced to provide some 
 guarantees.
 "strong pure" is useless because it shares same annotation 
 with "weak
 pure".
I think it's a great design, very useful and innovative.
Agree on it being great and innovative. But I fail to see usefulness with current design. Can you provide examples how current pure design allows for better code / optimizations?
Strongly pure functions can call weakly pure function while keeping its properties. So it loosen the constraint on strongly pure function while keeping the benefit.
Apr 09 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Wednesday, 10 April 2013 at 01:37:35 UTC, deadalnix wrote:
 Agree on it being great and innovative. But I fail to see 
 usefulness with current design. Can you provide examples how 
 current pure design allows for better code / optimizations?
Strongly pure functions can call weakly pure function while keeping its properties. So it loosen the constraint on strongly pure function while keeping the benefit.
It does not answer my question. Why "pure" keyword is useful in D if it does not guarantee that compiler will verify functional purity of you code and does not guarantee relevant optimizations? Beauty of concept is useless without practical application.
Apr 10 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 10 April 2013 at 08:19:26 UTC, Dicebot wrote:
 On Wednesday, 10 April 2013 at 01:37:35 UTC, deadalnix wrote:
 Agree on it being great and innovative. But I fail to see 
 usefulness with current design. Can you provide examples how 
 current pure design allows for better code / optimizations?
Strongly pure functions can call weakly pure function while keeping its properties. So it loosen the constraint on strongly pure function while keeping the benefit.
It does not answer my question. Why "pure" keyword is useful in D if it does not guarantee that compiler will verify functional purity of you code and does not guarantee relevant optimizations? Beauty of concept is useless without practical application.
It isn't beauty of concept. Strongly pure function exhibit from an external point of view the properties of pure as in functional programming.
Apr 10 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Wednesday, 10 April 2013 at 11:22:41 UTC, deadalnix wrote:
 On Wednesday, 10 April 2013 at 08:19:26 UTC, Dicebot wrote:
 On Wednesday, 10 April 2013 at 01:37:35 UTC, deadalnix wrote:
 Agree on it being great and innovative. But I fail to see 
 usefulness with current design. Can you provide examples how 
 current pure design allows for better code / optimizations?
Strongly pure functions can call weakly pure function while keeping its properties. So it loosen the constraint on strongly pure function while keeping the benefit.
It does not answer my question. Why "pure" keyword is useful in D if it does not guarantee that compiler will verify functional purity of you code and does not guarantee relevant optimizations? Beauty of concept is useless without practical application.
It isn't beauty of concept. Strongly pure function exhibit from an external point of view the properties of pure as in functional programming.
Except you can't be sure that your function is strongly pure with current design. Add ref parameter into the mix by accident and it will silently change to weak pure which is useless by its own.
Apr 10 2013
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/10/13 7:29 AM, Dicebot wrote:
 On Wednesday, 10 April 2013 at 11:22:41 UTC, deadalnix wrote:
 On Wednesday, 10 April 2013 at 08:19:26 UTC, Dicebot wrote:
 On Wednesday, 10 April 2013 at 01:37:35 UTC, deadalnix wrote:
 Agree on it being great and innovative. But I fail to see
 usefulness with current design. Can you provide examples how
 current pure design allows for better code / optimizations?
Strongly pure functions can call weakly pure function while keeping its properties. So it loosen the constraint on strongly pure function while keeping the benefit.
It does not answer my question. Why "pure" keyword is useful in D if it does not guarantee that compiler will verify functional purity of you code and does not guarantee relevant optimizations? Beauty of concept is useless without practical application.
It isn't beauty of concept. Strongly pure function exhibit from an external point of view the properties of pure as in functional programming.
Except you can't be sure that your function is strongly pure with current design.
I would venture that you are being confused. This seems to indicate insufficient documentation for 'pure'. Andrei
Apr 10 2013
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 10 April 2013 at 11:29:42 UTC, Dicebot wrote:
 Except you can't be sure that your function is strongly pure 
 with current design. Add ref parameter into the mix by accident 
 and it will silently change to weak pure which is useless by 
 its own.
pure + immutable and value parameters == strongly pure (as in functional). It is really that simple.
Apr 10 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/10/2013 05:43 PM, deadalnix wrote:
 On Wednesday, 10 April 2013 at 11:29:42 UTC, Dicebot wrote:
 Except you can't be sure that your function is strongly pure with
 current design. Add ref parameter into the mix by accident and it will
 silently change to weak pure which is useless by its own.
pure + immutable and value parameters == strongly pure (as in functional). It is really that simple.
pure notEntirely(){ return new Object(); } auto x = notEntirely(); assert(x is x); assert(notEntirely() !is notEntirely());
Apr 10 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 10 April 2013 at 15:48:43 UTC, Timon Gehr wrote:
 On 04/10/2013 05:43 PM, deadalnix wrote:
 On Wednesday, 10 April 2013 at 11:29:42 UTC, Dicebot wrote:
 Except you can't be sure that your function is strongly pure 
 with
 current design. Add ref parameter into the mix by accident 
 and it will
 silently change to weak pure which is useless by its own.
pure + immutable and value parameters == strongly pure (as in functional). It is really that simple.
pure notEntirely(){ return new Object(); } auto x = notEntirely(); assert(x is x); assert(notEntirely() !is notEntirely());
Yes, that is the entity vs value I discussed above n that thread. I should have said parameters AND return is a value.
Apr 10 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Wednesday, 10 April 2013 at 15:52:23 UTC, deadalnix wrote:
 ...
And that is exactly what makes it useless. I need one keyword to automatically verify for me that parameters fine, that context is fine, return value is fine etc. This is the basic crucial concept and everything else should be built on top of it, not other way around. No one can say that my function is pure just by seeing keyword because I have probably forgot something. It is like saying that immutable is immutable only if you take care of some cases. Outstanding issue in my opinion.
Apr 10 2013
parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 10 April 2013 at 17:12:27 UTC, Dicebot wrote:
 On Wednesday, 10 April 2013 at 15:52:23 UTC, deadalnix wrote:
 ...
And that is exactly what makes it useless. I need one keyword to automatically verify for me that parameters fine, that context is fine, return value is fine etc. This is the basic crucial concept and everything else should be built on top of it, not other way around. No one can say that my function is pure just by seeing keyword because I have probably forgot something. It is like saying that immutable is immutable only if you take care of some cases. Outstanding issue in my opinion.
Then you'd need 2 keyword, and one would be completely redundant with information already present in the signature.
Apr 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
On 10 April 2013 00:07, kenji hara <k.hara.pg gmail.com> wrote:

 2013/4/9 Dicebot <m.strashun gmail.com>

 On Tuesday, 9 April 2013 at 12:56:04 UTC, Andrei Alexandrescu wrote:

 It is valid code. It is "weak pure". "pure' keyword means both
 "strong pure" or "weak pure" depending on function body. Crap.
s/body/signature/ s/Crap/Awesome/
Not gonna argue latter but former is just wrong. struct Test { int a; pure int foo1() // strong pure { return 42; } pure int foo2() // weak pure { return a++; } } Signature is the same for both functions.
Both have weak pure. Purity is always calculated only from the function signature. If you make member function "strong pure", _at least_ it should be qualified with "immutable". pure int foo3() immutable // strong pure { return 10; } Kenji Hara
What is an immutable function? Why is const not sufficient?
Apr 09 2013
prev sibling next sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On 2013-04-09, 18:46, Manu wrote:

 What is an immutable function? Why is const not sufficient?
Immutable requires that the struct/class be immutable, const may be called on mutable instances. Thus, the object may be changed in a different thread while the const function executes. Not so with immutable. -- Simen
Apr 09 2013
parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 9 April 2013 at 16:55:07 UTC, Simen Kjaeraas wrote:
 On 2013-04-09, 18:46, Manu wrote:

 What is an immutable function? Why is const not sufficient?
Immutable requires that the struct/class be immutable, const may be called on mutable instances. Thus, the object may be changed in a different thread while the const function executes. Not so with immutable.
Not in other thread (as it would require to be shared or is undefined behavior) but vie delegate for instance.
Apr 09 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2013 6:49 AM, Dicebot wrote:
 Not gonna argue latter but former is just wrong.

 struct Test
 {
      int a;
      pure int foo1() // strong pure
      {
          return 42;
      }

      pure int foo2() // weak pure
      {
          return a++;
      }
 }

 Signature is the same for both functions.
foo1 is weakly pure. It would be strongly pure if it were declared: const pure int foo1();
Apr 10 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2013 5:56 AM, Andrei Alexandrescu wrote:
 s/body/signature/
 s/Crap/Awesome/
I agree that the notions of strong/weak purity are awesome, I believe they are a D innovation, and if I recall correctly this innovation is thanks to Don Clugston, one of our most awesome contributors.
Apr 10 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2013 1:04 AM, Dicebot wrote:
 On Tuesday, 9 April 2013 at 07:57:37 UTC, Manu wrote:
 Are you saying the example above is not actually valid code?

 struct Foo {
     int a = 0;
     pure int bar( int n ) { // Weakly pure
         a += n;
         return a;
     }
 }

 That's not pure. Call it twice with the same args, you'll different
 answers. How can that possibly be considered pure in any sense?
 And it's useless in terms of optimisation, so why bother at all? What does
 it offer?
It is valid code. It is "weak pure". "pure' keyword means both "strong pure" or "weak pure" depending on function body. Crap.
No, it is weakly or strongly pure based on the parameter types. bar(int n), for example, has an (implicit) mutable reference to 'this' in its parameter list. To be strongly pure, bar(int n) would have to be declared as: const pure int bar(int n); What the 'pure' keyword says is: "no reads/writes to mutable data from references that do not come through the parameters." Hence, if the parameters are all const or immutable, and it is marked pure, then the function is "strongly pure", meaning "no reads/writes to any externally visible mutable state". Notably, this is NOT determined by reading the function body, but by examining the parameter types. The reason for this behavior is so that strongly pure functions can call weakly pure struct/class methods, and yet remain strongly pure. Purity in D would be largely useless otherwise, as very very few functions could be strongly pure.
Apr 10 2013
prev sibling next sibling parent reply "Zach the Mystic" <reachzach gggggmail.com> writes:
On Tuesday, 9 April 2013 at 07:57:37 UTC, Manu wrote:
 Are you saying the example above is not actually valid code?

 struct Foo {
     int a = 0;
     pure int bar( int n ) { // Weakly pure
         a += n;
         return a;
     }
 }

 That's not pure. Call it twice with the same args, you'll 
 different
 answers. How can that possibly be considered pure in any sense?
 And it's useless in terms of optimisation, so why bother at 
 all? What does
 it offer?
deadalnix answered but too briefly it seems. I think the reason it's pure is because a struct's member functions are actually a kind of syntax sugar. Foo.bar above is rewritten underneath as something like: pure int __Foobar(ref Foo __f, int n) { __f.a += n; return __f.a; } Therefore if a were defined outside the struct, int a = 0; struct Foo { pure int bar( int n ) { a += n; // Epic fail return a; } } ... it would fail completely, but 'a' is a struct field and so passed by hidden pointer to the member function, which is therefore in essence weakly pure.
Apr 09 2013
parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 04/09/2013 10:21 AM, Zach the Mystic wrote:
 deadalnix answered but too briefly it seems. I think the reason it's pure is
 because a struct's member functions are actually a kind of syntax sugar.
Stepping outside from any controversy for now, I think I should say that these kind of in-depth discussions and explanations of the subtleties of language features (and programming theory in general) are one of the reasons I really, really enjoy being part of the D community. :-)
Apr 09 2013
parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Tuesday, 9 April 2013 at 16:41:08 UTC, Joseph Rushton Wakeling 
wrote:
 On 04/09/2013 10:21 AM, Zach the Mystic wrote:
 deadalnix answered but too briefly it seems. I think the 
 reason it's pure is
 because a struct's member functions are actually a kind of 
 syntax sugar.
Stepping outside from any controversy for now, I think I should say that these kind of in-depth discussions and explanations of the subtleties of language features (and programming theory in general) are one of the reasons I really, really enjoy being part of the D community. :-)
Thanks, man! The truth is, compared to some of the heavyweights here, I'm very new to programming. That being said, I DO endeavor to really understand what's going on with the inner workings. I don't want anything to be mysterious which doesn't have to be!
Apr 09 2013
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/9/13 3:56 AM, Manu wrote:
 Are you saying the example above is not actually valid code?

 struct Foo {
      int a = 0;
      pure int bar( int n ) { // Weakly pure
          a += n;
          return a;
      }
 }

 That's not pure. Call it twice with the same args, you'll different
 answers.
The values reachable from "this" are different in the two calls. Andrei
Apr 09 2013
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On 2013-04-08, 13:46, Iain Buclaw wrote:

 Only builtins are pure in the sense of 'C'.  Even functions considered
 PUREstrong by the frontend may update an internal state, so the rules  
 just
 don't apply.  Except for maybe global functions...   In any case, the  
 only
 benefit you can reap from 'D pure' functions are that they are more  
 likely
 to be const-folded / inlined.
What?!? Please give an example of this. What sort of internal state are we talking about here? -- Simen
Apr 08 2013
prev sibling next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 8 April 2013 14:40, Simen Kjaeraas <simen.kjaras gmail.com> wrote:

 On 2013-04-08, 13:46, Iain Buclaw wrote:

  Only builtins are pure in the sense of 'C'.  Even functions considered
 PUREstrong by the frontend may update an internal state, so the rules just
 don't apply.  Except for maybe global functions...   In any case, the only
 benefit you can reap from 'D pure' functions are that they are more likely
 to be const-folded / inlined.
What?!? Please give an example of this. What sort of internal state are we talking about here?
It might be weakly pure. ;) -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Apr 08 2013
prev sibling next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 8 April 2013 13:37, Manu <turkeyman gmail.com> wrote:

 Oh my god... ..... this is the most upsetting thing I've heard all day! :(
 No really, I have been SOOOO excited for so long about this optimisation
 potential in D!
 There's gotta be something that can be done! >_<

 Does the front end know if the function actually DOES assign to any state?
 The compiler could easily work that out, and in the event it doesn't
 actually perform any such assignment, it could be marked pure for reals...
Haven't looked, but it appears to have a general idea of this. D 'weak pure' and 'const pure' may update an internal state (had the latter bite me hard once). The only case where 'strong pure' might do this is by throwing an exception or an assert being thrown - this changes program state so can't be marked pure. So having identified this, we can safely say that functions could only be 'C pure' in the following case: - Compiled function is 'strong pure' - Compiled function is 'nothrow' - We are compiling in release mode. Only then we (the frontend) can safely say that 'this function has *absolutely* no side effects, so can be marked as pure'. Pure is never inferred. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Apr 08 2013
parent Johannes Pfau <nospam example.com> writes:
Am Mon, 8 Apr 2013 16:40:34 +0100
schrieb Iain Buclaw <ibuclaw ubuntu.com>:

 On 8 April 2013 13:37, Manu <turkeyman gmail.com> wrote:
 
 Oh my god... ..... this is the most upsetting thing I've heard all
 day! :( No really, I have been SOOOO excited for so long about this
 optimisation potential in D!
 There's gotta be something that can be done! >_<

 Does the front end know if the function actually DOES assign to any
 state? The compiler could easily work that out, and in the event it
 doesn't actually perform any such assignment, it could be marked
 pure for reals...
Haven't looked, but it appears to have a general idea of this. D 'weak pure' and 'const pure' may update an internal state (had the latter bite me hard once). The only case where 'strong pure' might do this is by throwing an exception or an assert being thrown - this changes program state so can't be marked pure. So having identified this, we can safely say that functions could only be 'C pure' in the following case: - Compiled function is 'strong pure' - Compiled function is 'nothrow' - We are compiling in release mode. Only then we (the frontend) can safely say that 'this function has *absolutely* no side effects, so can be marked as pure'. Pure is never inferred.
Can't a strong pure + nothrow + release mode function still throw errors? Or is this the "we don't guarantee anything regarding Errors" case and we just don't care?
Apr 08 2013
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 9 April 2013 01:40, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 8 April 2013 13:37, Manu <turkeyman gmail.com> wrote:

 Oh my god... ..... this is the most upsetting thing I've heard all day! :(
 No really, I have been SOOOO excited for so long about this optimisation
 potential in D!
 There's gotta be something that can be done! >_<

 Does the front end know if the function actually DOES assign to any
 state? The compiler could easily work that out, and in the event it doesn't
 actually perform any such assignment, it could be marked pure for reals...
Haven't looked, but it appears to have a general idea of this. D 'weak pure' and 'const pure' may update an internal state (had the latter bite me hard once). The only case where 'strong pure' might do this is by throwing an exception or an assert being thrown - this changes program state so can't be marked pure. So having identified this, we can safely say that functions could only be 'C pure' in the following case: - Compiled function is 'strong pure' - Compiled function is 'nothrow' - We are compiling in release mode. Only then we (the frontend) can safely say that 'this function has *absolutely* no side effects, so can be marked as pure'. Pure is never inferred.
How does one specify that in their code? Is 'strong pure' a keyword?
Apr 09 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 9 April 2013 at 07:41:55 UTC, Manu wrote:
 How does one specify that in their code? Is 'strong pure' a 
 keyword?
You can't and this is the most stupid thing about pure in D. Compiler can detect which one it is, but you can't force it to accept "pure" only as "strong pure".
Apr 09 2013
parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 04/09/2013 09:56 AM, Dicebot wrote:
 You can't and this is the most stupid thing about pure in D. Compiler can
detect
 which one it is, but you can't force it to accept "pure" only as "strong pure".
This is surely not so terrible -- it leaves the door open for a new keyword (strong pure actually seems quite good) which _does_ enforce that the function is strongly pure.
Apr 09 2013
prev sibling parent =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Tue, 09 Apr 2013 09:41:43 +0200, Manu <turkeyman gmail.com> wrote:

 How does one specify that in their code? Is 'strong pure' a keyword?
It's not a keyword. It's inferred by the compiler when a function is marked pure (or is a template function and is inferred pure), and all parameters are implicitly castable to immutable (i.e. POD or marked immutable). This includes, of course, the hidden 'this' parameter. -- Simen
Apr 09 2013
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-04-08 10:29, Iain Buclaw wrote:

 This information could possibly be helpful.  Though given that most of
 (gdc) codegen is on par with g++, there's probably not much on the list
 that isn't already detected by the backend optimisation passes.
Multiple calls to pure functions could be cached. -- /Jacob Carlborg
Apr 08 2013
next sibling parent reply Manu <turkeyman gmail.com> writes:
On 8 April 2013 22:25, Jacob Carlborg <doob me.com> wrote:

 On 2013-04-08 10:29, Iain Buclaw wrote:

  This information could possibly be helpful.  Though given that most of
 (gdc) codegen is on par with g++, there's probably not much on the list
 that isn't already detected by the backend optimisation passes.
Multiple calls to pure functions could be cached.
Not if it can still make external assignments though. pure in D is basically a lie! :,(
Apr 08 2013
next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 8 April 2013 at 12:41:23 UTC, Manu wrote:
 Not if it can still make external assignments though. pure in D 
 is
 basically a lie! :,(
A lie? It's merely a different definition, and the stronger variant can easily – particularly be a compiler – be recovered by checking the argument types. But yes, 'pure' should probably be the default in D. David
Apr 08 2013
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-04-08 14:41, Manu wrote:

 Not if it can still make external assignments though. pure in D is
 basically a lie! :,(
I'm taking about strong pure, whatever the difference is. I thought the the definition of "pure" was that it cannot touch global/external scope. -- /Jacob Carlborg
Apr 08 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Monday, 8 April 2013 at 12:25:01 UTC, Jacob Carlborg wrote:
 On 2013-04-08 10:29, Iain Buclaw wrote:

 This information could possibly be helpful.  Though given that 
 most of
 (gdc) codegen is on par with g++, there's probably not much on 
 the list
 that isn't already detected by the backend optimisation passes.
Multiple calls to pure functions could be cached.
As D have identity semantic, this isn't that simple.
Apr 08 2013
prev sibling next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 8 April 2013 13:25, Jacob Carlborg <doob me.com> wrote:

 On 2013-04-08 10:29, Iain Buclaw wrote:

  This information could possibly be helpful.  Though given that most of
 (gdc) codegen is on par with g++, there's probably not much on the list
 that isn't already detected by the backend optimisation passes.
Multiple calls to pure functions could be cached. -- /Jacob Carlborg
Not always, but in some circumstances, yes. --- struct Foo { int a = 0; pure int bar (immutable int x) { ++a; return x * 2; } } void main() { Foo f; int i = f.bar(2) + f.bar(2); assert (i == 8); assert (f.a == 2); } --- Again, the characteristics of D pure functions mean that the backend can const-fold away the function entirely under normal optimisations. --- D main () { <bb 2>: return 0; } --- Possibly strongly-pure functions could be marked as pure in the 'C' sense, but only if they are also nothrow, eg to add to the above example: --- pure nothrow int baz (Foo f) { return f.bar(2) + f.bar(2); } --- Regards -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Apr 08 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-04-08 14:52, Iain Buclaw wrote:
 On 8 April 2013 13:25, Jacob Carlborg <doob me.com <mailto:doob me.com>>
 wrote:

     On 2013-04-08 10:29, Iain Buclaw wrote:

         This information could possibly be helpful.  Though given that
         most of
         (gdc) codegen is on par with g++, there's probably not much on
         the list
         that isn't already detected by the backend optimisation passes.


     Multiple calls to pure functions could be cached.

     --
     /Jacob Carlborg


 Not always, but in some circumstances, yes.

 ---
 struct Foo
 {
    int a = 0;
    pure int bar (immutable int x)
    {
      ++a;
      return x * 2;
    }
 }


 void main()
 {
    Foo f;
    int i = f.bar(2) + f.bar(2);

    assert (i == 8);
    assert (f.a == 2);
 }
I though that wasn't possible. What's the point of pure if that's possible? -- /Jacob Carlborg
Apr 08 2013
next sibling parent "Dicebot" <m.strashun gmail.com> writes:
On Monday, 8 April 2013 at 15:07:31 UTC, Jacob Carlborg wrote:
 I though that wasn't possible. What's the point of pure if 
 that's possible?
Looks like one of problems that exist because "weakly pure" and "strongly pure" use the same keyword.
Apr 08 2013
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/08/2013 05:07 PM, Jacob Carlborg wrote:
 On 2013-04-08 14:52, Iain Buclaw wrote:
 On 8 April 2013 13:25, Jacob Carlborg <doob me.com <mailto:doob me.com>>
 wrote:

     On 2013-04-08 10:29, Iain Buclaw wrote:

         This information could possibly be helpful.  Though given that
         most of
         (gdc) codegen is on par with g++, there's probably not much on
         the list
         that isn't already detected by the backend optimisation passes.


     Multiple calls to pure functions could be cached.

     --
     /Jacob Carlborg


 Not always, but in some circumstances, yes.

 ---
 struct Foo
 {
    int a = 0;
    pure int bar (immutable int x)
    {
      ++a;
      return x * 2;
    }
 }


 void main()
 {
    Foo f;
    int i = f.bar(2) + f.bar(2);

    assert (i == 8);
    assert (f.a == 2);
 }
I though that wasn't possible. What's the point of pure if that's possible?
Foo.bar can be used in a strongly pure computation. It is superficially similar to how state transformers allow mutable state in Haskell. If you want more guarantees, you could mark a member function const, inout or immutable pure. DIP30 removes some optimization potential for at least const pure. Furthermore, the exact meaning of inout will have to be determined. Unfortunately it is both useful to have a specifier that prevents mutation but allows to return a mutable part of the function input and to have a specifier that allows mutation in case the function input is in fact mutable. Unfortunately, DMD does not implement type checking for delegates in a meaningful way. The specifiers const/immutable/pure should have consistent meanings for member functions and functions nested inside functions. (http://d.puremagic.com/issues/show_bug.cgi?id=9148)
Apr 08 2013
prev sibling next sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On 2013-04-08, 17:07, Jacob Carlborg wrote:

 On 2013-04-08 14:52, Iain Buclaw wrote:
 On 8 April 2013 13:25, Jacob Carlborg <doob me.com <mailto:doob me.com>>
 wrote:

     On 2013-04-08 10:29, Iain Buclaw wrote:

         This information could possibly be helpful.  Though given that
         most of
         (gdc) codegen is on par with g++, there's probably not much on
         the list
         that isn't already detected by the backend optimisation passes.


     Multiple calls to pure functions could be cached.

     --
     /Jacob Carlborg


 Not always, but in some circumstances, yes.

 ---
 struct Foo
 {
    int a = 0;
    pure int bar (immutable int x)
    {
      ++a;
      return x * 2;
    }
 }


 void main()
 {
    Foo f;
    int i = f.bar(2) + f.bar(2);

    assert (i == 8);
    assert (f.a == 2);
 }
I though that wasn't possible. What's the point of pure if that's possible?
Like others have stated, it's so you can do this: struct Foo { int a = 0; pure int bar( int n ) { // Weakly pure a += n; return a; } } pure int Baz( int n ) { // Strongly pure Foo foo; return foo.bar( n ); } Foo.bar has only local mutability, so if the Foo originated in a (strongly) pure function, Foo.bar can be called inside that pure function without violating the purity requirement. The three levels (weakly pure/strongly pure/impure) are needed, but a redesign would perhaps use a different keyword for weakly pure. -- Simen
Apr 08 2013
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-04-08 20:14, Simen Kjaeraas wrote:

 Like others have stated, it's so you can do this:

 struct Foo {
     int a = 0;
     pure int bar( int n ) { // Weakly pure
         a += n;
         return a;
     }
 }

 pure int Baz( int n ) { // Strongly pure
      Foo foo;
      return foo.bar( n );
 }

 Foo.bar has only local mutability, so if the Foo originated in a
 (strongly) pure function, Foo.bar can be called inside that pure
 function without violating the purity requirement.

 The three levels (weakly pure/strongly pure/impure) are needed,
 but a redesign would perhaps use a different keyword for weakly
 pure.
I see. -- /Jacob Carlborg
Apr 08 2013
prev sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Monday, 8 April 2013 at 18:15:11 UTC, Simen Kjaeraas wrote:
 The three levels (weakly pure/strongly pure/impure) are needed,
 but a redesign would perhaps use a different keyword for weakly
 pure.
Why should it? I mean, using another name for "pure" would arguably make sense, given the confusion it seems to have caused in the past. But if you are suggesting to differentiate between various "kinds of purity" on a keyword level, I'm not sure what benefits you are hoping to get. David
Apr 08 2013
parent "Dicebot" <m.strashun gmail.com> writes:
On Monday, 8 April 2013 at 19:48:50 UTC, David Nadlinger wrote:
 On Monday, 8 April 2013 at 18:15:11 UTC, Simen Kjaeraas wrote:
 The three levels (weakly pure/strongly pure/impure) are needed,
 but a redesign would perhaps use a different keyword for weakly
 pure.
Why should it? I mean, using another name for "pure" would arguably make sense, given the confusion it seems to have caused in the past. But if you are suggesting to differentiate between various "kinds of purity" on a keyword level, I'm not sure what benefits you are hoping to get. David
What will you do if you want to make Foo.bar _strongly_ pure and compiler to verify it?
Apr 08 2013
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Monday, 8 April 2013 at 15:07:31 UTC, Jacob Carlborg wrote:
 On 2013-04-08 14:52, Iain Buclaw wrote:
 On 8 April 2013 13:25, Jacob Carlborg <doob me.com 
 <mailto:doob me.com>>
 wrote:

    On 2013-04-08 10:29, Iain Buclaw wrote:

        This information could possibly be helpful.  Though 
 given that
        most of
        (gdc) codegen is on par with g++, there's probably not 
 much on
        the list
        that isn't already detected by the backend optimisation 
 passes.


    Multiple calls to pure functions could be cached.

    --
    /Jacob Carlborg


 Not always, but in some circumstances, yes.

 ---
 struct Foo
 {
   int a = 0;
   pure int bar (immutable int x)
   {
     ++a;
     return x * 2;
   }
 }


 void main()
 {
   Foo f;
   int i = f.bar(2) + f.bar(2);

   assert (i == 8);
   assert (f.a == 2);
 }
I though that wasn't possible. What's the point of pure if that's possible?
You have to think that this is an hidden parameter. The function touch that parameter, no global state.
Apr 08 2013
parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 04/09/13 02:44, deadalnix wrote:
 On Monday, 8 April 2013 at 15:07:31 UTC, Jacob Carlborg wrote:
 I though that wasn't possible. What's the point of pure if that's possible?
You have to think that this is an hidden parameter. The function touch that parameter, no global state.
D's pure is horribly misnamed; nobody that's not already aware of the D re-definition expects "pure" to mean what it currently does. struct S { int* p; int f() pure safe nothrow { return ++*p; } } int i = 1; int main() { auto s = S(&i); assert(i==1); auto r = s.f(); assert(r==2); r = s.f(); assert(r==3); assert(i==3); return r; } That's not pure by any definition, and fixing it w/o impacting valid cases would be non-trivial (think array members). artur
Apr 09 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2013 12:13 PM, Artur Skawina wrote:
 ...
 D's pure is horribly misnamed; nobody that's not already aware of the
 D re-definition expects "pure" to mean what it currently does.

     struct S {
        int* p;
        int f() pure  safe nothrow { return ++*p; }
     }

     int i = 1;

     int main() {
        auto s = S(&i);
        assert(i==1);
        auto r = s.f();
        assert(r==2);
        r = s.f();
        assert(r==3);
        assert(i==3);
        return r;
     }

 That's not pure by any definition,
I'd counter that it is pure by the D definition.
Apr 09 2013
next sibling parent kenji hara <k.hara.pg gmail.com> writes:
2013/4/9 Timon Gehr <timon.gehr gmx.ch>

 On 04/09/2013 12:13 PM, Artur Skawina wrote:
[snip]
 That's not pure by any definition,
I'd counter that it is pure by the D definition.
I completely agree with Timon. It's the definition in D. The meaning of 'pure' keyword in D *contains* widely used "pure" meaning, rather than differ. The usefulness of the three purity (weak-const-strong) is still there, and the keyword choice for the concept is enough reasonable. Kenji Hara
Apr 09 2013
prev sibling next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 04/09/13 12:51, kenji hara wrote:
 2013/4/9 Timon Gehr <timon.gehr gmx.ch <mailto:timon.gehr gmx.ch>>
 
     On 04/09/2013 12:13 PM, Artur Skawina wrote:
 
 [snip] 
 
 
         That's not pure by any definition,
 
 
     I'd counter that it is pure by the D definition.
 
 
 I completely agree with Timon. It's the definition in D.
A function that both directly depends on global mutable state (and modifies it) can hardly be called pure. Can you (anybody) give a D "pure" definition that allows for the program that I've posted and still makes "pure" useful? artur
Apr 09 2013
prev sibling next sibling parent reply =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Tue, 09 Apr 2013 13:10:16 +0200, Artur Skawina <art.08.09 gmail.com>  
wrote:

 A function that both directly depends on global mutable state (and
 modifies it) can hardly be called pure. Can you (anybody) give a
 D "pure" definition that allows for the program that I've posted
 and still makes "pure" useful?
Functions that are pure may only mutate mutable state explicitly passed to them, or created within. There. That's basically all there is to D's pure. From this definition arise some useful properties, e.g. that a function whose parameters are all immutable or implicitly castable to immutable, is referentially transparent. -- Simen
Apr 09 2013
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2013 01:47 PM, Simen Kjærås wrote:
 On Tue, 09 Apr 2013 13:10:16 +0200, Artur Skawina <art.08.09 gmail.com>
 wrote:

 A function that both directly depends on global mutable state (and
 modifies it) can hardly be called pure. Can you (anybody) give a
 D "pure" definition that allows for the program that I've posted
 and still makes "pure" useful?
Functions that are pure may only mutate mutable state explicitly passed to them, or created within. There. That's basically all there is to D's pure. From this definition arise some useful properties, e.g. that a function whose parameters are all immutable or implicitly castable to immutable, is referentially transparent.
pure notReferentiallyTransparent(){ // forall vacuously true return new Object(); }
Apr 09 2013
prev sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 04/09/13 13:47, Simen Kjærås wrote:
 On Tue, 09 Apr 2013 13:10:16 +0200, Artur Skawina <art.08.09 gmail.com> wrote:
 
 A function that both directly depends on global mutable state (and
 modifies it) can hardly be called pure. Can you (anybody) give a
 D "pure" definition that allows for the program that I've posted
 and still makes "pure" useful?
Functions that are pure may only mutate mutable state explicitly passed to them, or created within.
struct S; int f(S* p) pure; S* n(); int g = 0; int main() { S* s = n(); f(s); return g; } Is main() guaranteed to return '0'? artur
Apr 09 2013
next sibling parent "Tobias Pankrath" <tobias pankrath.net> writes:
    struct S;
    int f(S* p) pure;
    S* n();

    int g = 0;
 
    int main() {
       S* s = n();
       f(s);
       return g;
    }

 Is main() guaranteed to return '0'?
 
 artur
Dunno, how this makes an example if you use at least 2, probably 3 non pure functions (main, n, constructor of S).
Apr 09 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2013 03:18 PM, Artur Skawina wrote:
 On 04/09/13 13:47, Simen Kjærås wrote:
 On Tue, 09 Apr 2013 13:10:16 +0200, Artur Skawina <art.08.09 gmail.com> wrote:

 A function that both directly depends on global mutable state (and
 modifies it) can hardly be called pure. Can you (anybody) give a
 D "pure" definition that allows for the program that I've posted
 and still makes "pure" useful?
Functions that are pure may only mutate mutable state explicitly passed to them, or created within.
struct S; int f(S* p) pure; S* n(); int g = 0; int main() { S* s = n(); f(s); return g; } Is main() guaranteed to return '0'? artur
No. What is the point?
Apr 09 2013
parent Artur Skawina <art.08.09 gmail.com> writes:
On 04/09/13 15:22, Timon Gehr wrote:
 On 04/09/2013 03:18 PM, Artur Skawina wrote:
 On 04/09/13 13:47, Simen Kjærås wrote:
 On Tue, 09 Apr 2013 13:10:16 +0200, Artur Skawina <art.08.09 gmail.com> wrote:

 A function that both directly depends on global mutable state (and
 modifies it) can hardly be called pure. Can you (anybody) give a
 D "pure" definition that allows for the program that I've posted
 and still makes "pure" useful?
Functions that are pure may only mutate mutable state explicitly passed to them, or created within.
struct S; int f(S* p) pure; S* n(); int g = 0; int main() { S* s = n(); f(s); return g; } Is main() guaranteed to return '0'?
No. What is the point?
I'm exploring the D purity definition given above, which is either incorrect or extremely misleading. My example was bad though, as it had too many unstated assumptions. A better one would have been: struct S; int g; int f(S* p) pure; int h(S* s) { g = 0; f(s); return g; } // Is 'h' guaranteed to return '0'? Obviously, the answer is no. Yet this will be expected by anyone not aware of how "pure" works in D. Adding "const" would only change the R/W dep to a R/O one (IOW 'f' could still return different values depending on 'g'). artur
Apr 09 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
On 9 April 2013 01:07, Jacob Carlborg <doob me.com> wrote:

 On 2013-04-08 14:52, Iain Buclaw wrote:

 On 8 April 2013 13:25, Jacob Carlborg <doob me.com <mailto:doob me.com>>

 wrote:

     On 2013-04-08 10:29, Iain Buclaw wrote:

         This information could possibly be helpful.  Though given that
         most of
         (gdc) codegen is on par with g++, there's probably not much on
         the list
         that isn't already detected by the backend optimisation passes.


     Multiple calls to pure functions could be cached.

     --
     /Jacob Carlborg


 Not always, but in some circumstances, yes.

 ---
 struct Foo
 {
    int a = 0;
    pure int bar (immutable int x)
    {
      ++a;
      return x * 2;
    }
 }


 void main()
 {
    Foo f;
    int i = f.bar(2) + f.bar(2);

    assert (i == 8);
    assert (f.a == 2);
 }
I though that wasn't possible. What's the point of pure if that's possible?
Precisely >_<
Apr 09 2013
prev sibling next sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 04/08/2013 08:14 PM, Simen Kjaeraas wrote:
 Like others have stated, it's so you can do this:
 
 struct Foo {
    int a = 0;
    pure int bar( int n ) { // Weakly pure
        a += n;
        return a;
    }
 }
 
 pure int Baz( int n ) { // Strongly pure
     Foo foo;
     return foo.bar( n );
 }
... one clear application of this being pseudo-random number generation, where you have a state variable together with a (pure) update function.
Apr 09 2013
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 9 April 2013 19:43, Joseph Rushton Wakeling <joseph.wakeling webdrake.net
 wrote:
 On 04/08/2013 08:14 PM, Simen Kjaeraas wrote:
 Like others have stated, it's so you can do this:

 struct Foo {
    int a = 0;
    pure int bar( int n ) { // Weakly pure
        a += n;
        return a;
    }
 }

 pure int Baz( int n ) { // Strongly pure
     Foo foo;
     return foo.bar( n );
 }
... one clear application of this being pseudo-random number generation, where you have a state variable together with a (pure) update function.
There's nothing 'pure' about a function that has side effects. It's a totally different concept, and should be named appropriately.
Apr 09 2013
next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Tuesday, 9 April 2013 at 10:28:16 UTC, Manu wrote:
 There's nothing 'pure' about a function that has side effects. 
 It's a
 totally different concept, and should be named appropriately.
It's not totally different – the possible side effects are still very localized and controllable by the *caller* (not the callee). But yes, the name is a bit unfortunate, and has historical reasons. As to not repeat myself, I'll just link to an article I wrote a couple of months ago: http://klickverbot.at/blog/2012/05/purity-in-d/#weak_purity_allows_for_stronger_guarantees David
Apr 09 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2013 12:28 PM, Manu wrote:
 ...

 There's nothing 'pure' about a function that has side effects.
If it has the same side effects every time it is called with the same arguments, then there is something pure about it.
 It's a totally different concept,
The concept of mutation can be expressed easily in a language not directly supporting side effects. Just pass around the store explicitly. The term you want to describe is presumably referential transparency.
 and should be named appropriately.
I guess nobody will disagree with this.
Apr 09 2013
parent reply Manu <turkeyman gmail.com> writes:
On 9 April 2013 20:50, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 04/09/2013 12:28 PM, Manu wrote:

 ...


 There's nothing 'pure' about a function that has side effects.
If it has the same side effects every time it is called with the same arguments, then there is something pure about it.
But it doesn't. It could do anything when called a second time, same arguments or not. The only thing it can't do is escape a variable. That sounds more like 'scope' to me than 'pure'.
Apr 09 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2013 01:26 PM, Manu wrote:
 On 9 April 2013 20:50, Timon Gehr <timon.gehr gmx.ch
 <mailto:timon.gehr gmx.ch>> wrote:

     On 04/09/2013 12:28 PM, Manu wrote:

         ...


         There's nothing 'pure' about a function that has side effects.


     If it has the same side effects every time it is called with the
     same arguments, then there is something pure about it.


 But it doesn't. It could do anything when called a second time, same
 arguments or not.
Well, no. That's the point. Feel free to provide an example where you think this property is violated. (However, note that the concept of the 'same arguments', and the 'same side effects' is informal and would need a little clarification.)
 The only thing it can't do is escape a variable. That sounds more like
 'scope' to me than 'pure'.
That is not the only thing it can't do.
Apr 09 2013
prev sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Tuesday, 9 April 2013 at 11:26:38 UTC, Manu wrote:
 But it doesn't. It could do anything when called a second time, 
 same
 arguments or not.
Can it? David
Apr 09 2013
prev sibling parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 04/09/2013 12:28 PM, Manu wrote:
 There's nothing 'pure' about a function that has side effects. It's a totally
 different concept, and should be named appropriately.
But a natural way to define a pseudo-random number generator is a combination of a state variable together with a pure function that takes the current state variable and returns the next in the sequence -- see e.g.: http://www.cs.berkeley.edu/~mhoemmen/cs194/Tutorials/prng.pdf (Hope I'm not being condescending here, as I imagine you know the theory of this better than I do.) So, I'm not sure I see the disadvantage of allowing a slight relaxation in purity that allows one to combine the state variable and transition function together in a single struct -- which is pretty much analogous to what's happening in the given examples where a private variable is being incremented by a 'pure' function. I do agree that it's a great pity there is not a way to declare strong purity for D functions.
Apr 09 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2013 3:52 AM, Joseph Rushton Wakeling wrote:
 I do agree that it's a great pity there is not a way to declare strong purity
 for D functions.
Sure there is. Declare the function as pure, and the function's parameters as const or immutable.
Apr 10 2013
parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 04/10/2013 08:39 PM, Walter Bright wrote:
 Sure there is. Declare the function as pure, and the function's parameters as
 const or immutable.
Sure, I accept that. What I was meaning, though, was an up-front declaration which would make the compiler shout if those necessary conditions were not met. i.e. pure foo(int n) { ... } // compiles strong pure bar(int n) { ... } // compiler instructs you to make // variables const or immutable
Apr 11 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 11 April 2013 at 08:36:13 UTC, Joseph Rushton 
Wakeling wrote:
 On 04/10/2013 08:39 PM, Walter Bright wrote:
 Sure there is. Declare the function as pure, and the 
 function's parameters as
 const or immutable.
Sure, I accept that. What I was meaning, though, was an up-front declaration which would make the compiler shout if those necessary conditions were not met. i.e. pure foo(int n) { ... } // compiles strong pure bar(int n) { ... } // compiler instructs you to make // variables const or immutable
Both are strongly pure.
Apr 11 2013
next sibling parent reply =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Thu, 11 Apr 2013 12:03:38 +0200, deadalnix <deadalnix gmail.com> wrote:

 On Thursday, 11 April 2013 at 08:36:13 UTC, Joseph Rushton Wakeling  
 wrote:
 On 04/10/2013 08:39 PM, Walter Bright wrote:
 Sure there is. Declare the function as pure, and the function's  
 parameters as
 const or immutable.
Sure, I accept that. What I was meaning, though, was an up-front declaration which would make the compiler shout if those necessary conditions were not met. i.e. pure foo(int n) { ... } // compiles strong pure bar(int n) { ... } // compiler instructs you to make // variables const or immutable
Both are strongly pure.
That's not the point. The point is, if he'd written this: strong pure bar(int* n) { ... } The compiler would have said 'Bad programmer! int* is not implicitly castable to immutable!' -- Simen
Apr 11 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-04-11 12:09, Simen Kjærås wrote:

 That's not the point. The point is, if he'd written this:

    strong pure bar(int* n) { ... }

 The compiler would have said 'Bad programmer! int* is not implicitly
 castable to immutable!'
What's the point of that. Just have "strong" mean const/immutable parameters. -- /Jacob Carlborg
Apr 11 2013
next sibling parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 04/11/2013 03:29 PM, Jacob Carlborg wrote:
 What's the point of that. Just have "strong" mean const/immutable parameters.
The point is to have a way for me, the programmer, to say to the compiler: "I mean for this function to be strongly pure, can you confirm whether my choice of function inputs supports this please?"
Apr 11 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-04-11 15:38, Joseph Rushton Wakeling wrote:

 The point is to have a way for me, the programmer, to say to the compiler: "I
 mean for this function to be strongly pure, can you confirm whether my choice
of
 function inputs supports this please?"
Why should I have to explicitly specify "immutable" when that could be default for strongly pure functions? -- /Jacob Carlborg
Apr 11 2013
parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 04/11/2013 08:16 PM, Jacob Carlborg wrote:
 Why should I have to explicitly specify "immutable" when that could be default
 for strongly pure functions?
Oh, sorry, I misunderstood your meaning. I thought you were saying that a "strong pure" keyword wasn't necessary because it was sufficient to have pure with immutable/const input.
Apr 11 2013
prev sibling next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 11 April 2013 14:38, Joseph Rushton Wakeling <
joseph.wakeling webdrake.net> wrote:

 On 04/11/2013 03:29 PM, Jacob Carlborg wrote:
 What's the point of that. Just have "strong" mean const/immutable
parameters. The point is to have a way for me, the programmer, to say to the compiler: "I mean for this function to be strongly pure, can you confirm whether my choice of function inputs supports this please?"
I think that giving the user choice of purity is about as useful as given user choice over what functions should be inlined, or what vars should go in registers. Such decisions are best left to the compiler devs judgement on doing the right thing for you. Even if they sometimes get it wrong. :o) -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Apr 11 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-04-11 15:53, Iain Buclaw wrote:

 I think that giving the user choice of purity is about as useful as
 given user choice over what functions should be inlined, or what vars
 should go in registers.

 Such decisions are best left to the compiler devs judgement on doing the
 right thing for you.  Even if they sometimes get it wrong. :o)
Beside from optimizations, it could good to be able to mark functions as pure, form a design point of view. I might be more easy to reason about a piece of code. -- /Jacob Carlborg
Apr 11 2013
prev sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 04/11/2013 03:53 PM, Iain Buclaw wrote:
 I think that giving the user choice of purity is about as useful as given user
 choice over what functions should be inlined, or what vars should go in
registers.
Well, I don't mean the compiler should guarantee that my code will be optimized in a certain way, but it's handy to be able to verify that it _qualifies_ for those optimizations. That said, I think my suggestion is a minor convenience feature, and is much, much less important than ironing out the design/implementation issues that others have raised in this thread.
 Such decisions are best left to the compiler devs judgement on doing the right
 thing for you.  Even if they sometimes get it wrong. :o)
What??!! You guys get it wrong sometimes??!! :-O
Apr 11 2013
prev sibling next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Thursday, 11 April 2013 at 10:03:39 UTC, deadalnix wrote:
 On Thursday, 11 April 2013 at 08:36:13 UTC, Joseph Rushton 
 Wakeling wrote:
 On 04/10/2013 08:39 PM, Walter Bright wrote:
 Sure there is. Declare the function as pure, and the 
 function's parameters as
 const or immutable.
Sure, I accept that. What I was meaning, though, was an up-front declaration which would make the compiler shout if those necessary conditions were not met. i.e. pure foo(int n) { ... } // compiles strong pure bar(int n) { ... } // compiler instructs you to make // variables const or immutable
Both are strongly pure.
is foo strongly pure because of n being a value type that cannot contain any indirection? (i.e. as far as the outside world is concerned you don't get any side effects whatever you do with it). Is the same for structs that contain no indirection? Or do they have to be const/immutable?
Apr 11 2013
next sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
2013/4/11 John Colvin <john.loughran.colvin gmail.com>

 On Thursday, 11 April 2013 at 10:03:39 UTC, deadalnix wrote:

 On Thursday, 11 April 2013 at 08:36:13 UTC, Joseph Rushton Wakeling wrote:

 On 04/10/2013 08:39 PM, Walter Bright wrote:

 Sure there is. Declare the function as pure, and the function's
 parameters as
 const or immutable.
Sure, I accept that. What I was meaning, though, was an up-front declaration which would make the compiler shout if those necessary conditions were not met. i.e. pure foo(int n) { ... } // compiles strong pure bar(int n) { ... } // compiler instructs you to make // variables const or immutable
Both are strongly pure.
is foo strongly pure because of n being a value type that cannot contain any indirection? (i.e. as far as the outside world is concerned you don't get any side effects whatever you do with it). Is the same for structs that contain no indirection? Or do they have to be const/immutable?
It is same for structs that has no *mutable* indirections. In below, all functions are strongly pure. module x; struct S1 { int n; } struct S2 { immutable int[] arr; } struct S3 { int[] arr; } pure int foo0(int n); pure int foo1(S1); // S1 has no indirections pure int foo2(S2); // S2 has no *mutable* indirections pure int foo3(immutable ref S3 x); // foo3 cannot access any mutable indirections Kenji Hara
Apr 11 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Thursday, 11 April 2013 at 10:27:55 UTC, kenji hara wrote:
 2013/4/11 John Colvin <john.loughran.colvin gmail.com>

 On Thursday, 11 April 2013 at 10:03:39 UTC, deadalnix wrote:

 On Thursday, 11 April 2013 at 08:36:13 UTC, Joseph Rushton 
 Wakeling wrote:

 On 04/10/2013 08:39 PM, Walter Bright wrote:

 Sure there is. Declare the function as pure, and the 
 function's
 parameters as
 const or immutable.
Sure, I accept that. What I was meaning, though, was an up-front declaration which would make the compiler shout if those necessary conditions were not met. i.e. pure foo(int n) { ... } // compiles strong pure bar(int n) { ... } // compiler instructs you to make // variables const or immutable
Both are strongly pure.
is foo strongly pure because of n being a value type that cannot contain any indirection? (i.e. as far as the outside world is concerned you don't get any side effects whatever you do with it). Is the same for structs that contain no indirection? Or do they have to be const/immutable?
It is same for structs that has no *mutable* indirections. In below, all functions are strongly pure. module x; struct S1 { int n; } struct S2 { immutable int[] arr; } struct S3 { int[] arr; } pure int foo0(int n); pure int foo1(S1); // S1 has no indirections pure int foo2(S2); // S2 has no *mutable* indirections pure int foo3(immutable ref S3 x); // foo3 cannot access any mutable indirections Kenji Hara
right, gotcha!
Apr 11 2013
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 11 April 2013 at 10:16:39 UTC, John Colvin wrote:
 On Thursday, 11 April 2013 at 10:03:39 UTC, deadalnix wrote:
 On Thursday, 11 April 2013 at 08:36:13 UTC, Joseph Rushton 
 Wakeling wrote:
 On 04/10/2013 08:39 PM, Walter Bright wrote:
 Sure there is. Declare the function as pure, and the 
 function's parameters as
 const or immutable.
Sure, I accept that. What I was meaning, though, was an up-front declaration which would make the compiler shout if those necessary conditions were not met. i.e. pure foo(int n) { ... } // compiles strong pure bar(int n) { ... } // compiler instructs you to make // variables const or immutable
Both are strongly pure.
is foo strongly pure because of n being a value type that cannot contain any indirection? (i.e. as far as the outside world is concerned you don't get any side effects whatever you do with it). Is the same for structs that contain no indirection? Or do they have to be const/immutable?
I don't know what the current implementation says, but it should be.
Apr 11 2013
prev sibling next sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 04/11/2013 12:03 PM, deadalnix wrote:
 Both are strongly pure.
Perhaps the fact that I can have this misunderstanding is itself an argument for an explicit "strong pure" keyword, so that a daft bugger like me can really be sure he's getting what he thinks he's getting? :-) Apart from that, I think Simen replied better than I could ...
Apr 11 2013
prev sibling next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 11 April 2013 11:09, Simen Kj=E6r=E5s <simen.kjaras gmail.com> wrote:

 On Thu, 11 Apr 2013 12:03:38 +0200, deadalnix <deadalnix gmail.com> wrote=
:
  On Thursday, 11 April 2013 at 08:36:13 UTC, Joseph Rushton Wakeling wrot=
e:
 On 04/10/2013 08:39 PM, Walter Bright wrote:

 Sure there is. Declare the function as pure, and the function's
 parameters as
 const or immutable.
Sure, I accept that. What I was meaning, though, was an up-front declaration which would make the compiler shout if those necessary conditions were not met. i.e. pure foo(int n) { ... } // compiles strong pure bar(int n) { ... } // compiler instructs you to make // variables const or immutable
Both are strongly pure.
That's not the point. The point is, if he'd written this: strong pure bar(int* n) { ... } The compiler would have said 'Bad programmer! int* is not implicitly castable to immutable!'
Great, just what we need. A compiler that barrages the user about how bad his code is, then dies... </sarcasm> --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
Apr 11 2013
prev sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 04/11/2013 03:49 PM, Iain Buclaw wrote:
 Great, just what we need.  A compiler that barrages the user about how bad his
 code is, then dies...
"Compiler says no ..."
Apr 11 2013
prev sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
 Possibly strongly-pure functions could be marked as pure in the 'C' sense,
 but only if they are also nothrow, eg to add to the above example:

 ---
 pure nothrow int baz (Foo f)
 {
   return f.bar(2) + f.bar(2);
 }
 ---
Or a better example that could also be pure in the 'C' sense. int baz (Foo f) pure nothrow { return f.bar(f.a) + f.bar(f.a); } -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Apr 08 2013
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
To: NG D
Subject: Re: To help LDC/GDC

This D code comes from a Haskell solution by tanakh of the 
Lawnmower problem of the Google Code Jam 2013 Qualification Round:


import std.stdio, std.string, std.conv, std.range, std.algorithm;

void main() {
   immutable n = stdin.readln.strip.to!int;

   foreach (immutable cn; 1 .. n + 1) {
     const hw = stdin.readln.split.to!(int[]);
     const bd = hw[0].iota.map!(i => 
stdin.readln.split.to!(int[])).array;
     const tbd = hw[1].iota.map!(i => 
bd.transversal(i).array).array;

     bool checkH(in int ch) {
       const okX = tbd.map!(xl => xl.all!(x => x <= ch)).array;
       foreach (oky, r; bd.map!(yl => yl.all!(y => y <= 
ch)).zip(bd))
         //foreach (okx, c; tbd.map!(xl => xl.all!(x => x <= 
ch)).zip(r))//Slow.
         foreach (okx, c; okX.zip(r))
           if (c <= ch && !(okx || oky))
             return false;
       return true;
     }


: "NO");
   }
}



In the inner foreach I have had to compute okX before the loops 
otherwise the code gets several times slower. Is such 
optimization possible from a D compiler? Both "map" and "all" 
should be pure. The Haskell compiler uses library-defined 
"rewrite rules" to help in such cases.

Bye,
bearophile
May 02 2013