www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why is immutable not possible as a result of a reduce expression?

reply "Michael Engelhardt" <me mindcrime-ilab.de> writes:
Hi,
just playing around with the functional capabilities of D. One 
concept of the pure functional programming is that variables 
should not be reassigned, so the best(?) way to assure this is 
using immutable:

     immutable auto gen = sequence!("n");
     immutable auto seq = take(gen,10);
     immutable auto filtered = filter!("a % 3 == 0 || a % 5 
==0")(seq);
     immutable auto sum = reduce!("a+b")(filtered);

but the last line gives a compiler error:

Error: template instance 
std.algorithm.reduce!("a+b").reduce!(immutable(FilterResult!(unaryFun,immutable(Take!(immutable(Sequence!
"n",Tuple!()))))))) 
error instantiating

It compiles and run as expected if I remove the immutable 
constraint on the reduce expression. So what is happening here? I 
thought reduce will create a new data structure containing the 
resulting values like filter and other operations too? That seems 
not to be the case, maybe someone could give me a deeper 
understanding of this.

Thanks in advance

Michael
Jan 05 2013
next sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On 2013-52-05 20:01, Michael Engelhardt <me mindcrime-ilab.de> wrote:

 Hi,
 just playing around with the functional capabilities of D. One concept  
 of the pure functional programming is that variables should not be  
 reassigned, so the best(?) way to assure this is using immutable:

      immutable auto gen = sequence!("n");
      immutable auto seq = take(gen,10);
      immutable auto filtered = filter!("a % 3 == 0 || a % 5 ==0")(seq);
      immutable auto sum = reduce!("a+b")(filtered);

 but the last line gives a compiler error:

 Error: template instance  
 std.algorithm.reduce!("a+b").reduce!(immutable(FilterResult!(unaryFun,immutable(Take!(immutable(Sequence!
"n",Tuple!())))))))  
 error instantiating

 It compiles and run as expected if I remove the immutable constraint on  
 the reduce expression. So what is happening here? I thought reduce will  
 create a new data structure containing the resulting values like filter  
 and other operations too? That seems not to be the case, maybe someone  
 could give me a deeper understanding of this.
The reason is that ranges may not be immutable or const. Ranges need to be mutated (popFront) to be iterable, and your filtered range cannot be mutated, by virtue of being immutable. I'm surprised that seq and filtered work, but I guess there may be specializations that circumvent the problem. In other words, remove immutable from the first three lines, and the program should compile. A little details is that immutable auto is unnecessary, as immutable implies auto (the details are more complex, but that's the short version). -- Simen
Jan 05 2013
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Saturday, 5 January 2013 at 20:09:24 UTC, Simen Kjaeraas wrote:
 The reason is that ranges may not be immutable or const.

 Ranges need to be mutated (popFront) to be iterable, and your 
 filtered
 range cannot be mutated, by virtue of being immutable. I'm 
 surprised that
 seq and filtered work, but I guess there may be specializations 
 that
 circumvent the problem.
No, they just make the erroneous assumption that copying strips immutablity. There are cases where this is true, but not always. The *only* time when this is true is with arrays, where "immutable(T[])" can be copied to a "immutable(T)[]". Even then, the compiler strips to top immutable of the type implicitly, so no extra code should be rolled out for it anyways... IMO, the only sensible behavior when calling "auto filter!(immutable R)(r)" would be to return an "immutable Filter!R" initialized with r... ...but you'd have to do it with the actual "immutable constructor". Simply creating a Filter!R and then castng it to immutable would also be wrong. Ditto for all other range types. I'll try and review them.
Jan 05 2013
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 01/05/2013 12:09 PM, Simen Kjaeraas wrote:

 A little details is that immutable auto is unnecessary, as immutable
 implies auto (the details are more complex, but that's the short 
version). It is true that the OP does not need auto when there is already immutable but does immutable really imply auto, or are they orthogonal? Ali P.S. I had wrongly assumed that D's auto was the same as C++11's auto and that it came from "automatic type deduction." That is not true in D. As in C and old C++, D's auto comes from "automatic storage duration." We still use it for automatic type deduction to make the syntax happy when there is no other keyword to put to the left of the symbol.
Jan 05 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, January 05, 2013 16:18:51 Ali =C3=87ehreli wrote:
 On 01/05/2013 12:09 PM, Simen Kjaeraas wrote:
  > A little details is that immutable auto is unnecessary, as immutab=
le
  > implies auto (the details are more complex, but that's the short
=20
 version).
=20
 It is true that the OP does not need auto when there is already
 immutable but does immutable really imply auto, or are they orthogona=
l?
=20
 Ali
=20
 P.S. I had wrongly assumed that D's auto was the same as C++11's auto=
 and that it came from "automatic type deduction." That is not true in=
D.
 As in C and old C++, D's auto comes from "automatic storage duration.=
"
 We still use it for automatic type deduction to make the syntax happy=
 when there is no other keyword to put to the left of the symbol.
D's auto _is_ automatic type deduction like in C++11. It's just that co= nst,=20 immutable, and enum also deduce the type if you don't give it (with the= =20 addition of making the type const or immutable in the cases of const an= d=20 immutable). auto a =3D 1; const c =3D 1; immutable i =3D 1; enum e =3D 1; all do type inferrence and all work just fine. - Jonathan M Davis
Jan 05 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 01/05/2013 04:59 PM, Jonathan M Davis wrote:

 D's auto _is_ automatic type deduction like in C++11.
It must have changed in the last couple of years. I see that the documentation is now different: http://dlang.org/attribute.html#auto It now says "The auto attribute is used when there are no other attributes and type inference is desired." It used to be not the case. The historical evidence is still there in compiler error messages: auto auto a = 1; Error: redundant storage class 'auto' ;) Ali
Jan 05 2013
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, January 05, 2013 17:15:51 Ali =C3=87ehreli wrote:
 On 01/05/2013 04:59 PM, Jonathan M Davis wrote:
  > D's auto _is_ automatic type deduction like in C++11.
=20
 It must have changed in the last couple of years. I see that the
 documentation is now different:
=20
    http://dlang.org/attribute.html#auto
=20
 It now says "The auto attribute is used when there are no other
 attributes and type inference is desired."
=20
 It used to be not the case. The historical evidence is still there in=
 compiler error messages:
=20
      auto auto a =3D 1;
=20
 Error: redundant storage class 'auto'
=20
 ;)
In D, the term storage class is used for pretty much any attribute on a= =20 variable which is not a type constructor and therefore affects the actu= al type=20 (i.e. const and immutable). So, in that sense, auto _is_ a storage clas= s, but=20 the term is pretty meaningless. C and C++ have a stricter definition of= the=20 term storage class. - Jonathan M Davis
Jan 05 2013
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/6/13, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 In D, the term storage class is used for pretty much any attribute on a
 variable which is not a type constructor
This topic pops up in the newsgroups every once in a while[1]. Maybe we should properly document it in the docs, a special section on storage class vs type qualifier (or type constructor or whatever it's called). There is documentation for function parameter storage classes[2], but that's about it. 1: http://www.digitalmars.com/d/archives/digitalmars/D/Definitive_list_of_storage_classes_164063.html 2: http://dlang.org/function.html#parameters
Jan 05 2013
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, January 06, 2013 05:33:04 Andrej Mitrovic wrote:
 On 1/6/13, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 In D, the term storage class is used for pretty much any attribute on a
 variable which is not a type constructor
This topic pops up in the newsgroups every once in a while[1]. Maybe we should properly document it in the docs, a special section on storage class vs type qualifier (or type constructor or whatever it's called). There is documentation for function parameter storage classes[2], but that's about it. 1: http://www.digitalmars.com/d/archives/digitalmars/D/Definitive_list_of_stor age_classes_164063.html 2: http://dlang.org/function.html#parameters
Well, since no one (including Walter or Andrei) could give a propery definition for storage class last time I brought it up, I don't know what we'd put in the docs. If you or someone else can come up with something appropriate though, that would be great. It's clear which are type qualifiers / constructors, but everything else has to be inferred from that. - Jonathan M Davis
Jan 06 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/6/13, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 If you or someone else
It's going to have to be someone else. When someone asks something on IRC/NG and another person responds with "it's because it's not a type constructor", or "it's not a storage class" I get completely thrown off and don't understand what they mean, exactly because there's no solid definition in the docs.
Jan 06 2013
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, January 06, 2013 21:59:32 Andrej Mitrovic wrote:
 On 1/6/13, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 If you or someone else
It's going to have to be someone else. When someone asks something on IRC/NG and another person responds with "it's because it's not a type constructor", or "it's not a storage class" I get completely thrown off and don't understand what they mean, exactly because there's no solid definition in the docs.
Well, I think that we can get a solid definiton for a type qualifier / constructor fairly easily, but storage class is harder, because there really isn't one. - Jonathan M Davis
Jan 06 2013