www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.array.array and immutable elements

reply "Jack Applegame" <japplegame gmail.com> writes:
DMD64 D Compiler v2.066.1
Why second call doesn't compile?

import std.array;
import std.algorithm;

class Foo {
	bool flag;
}
void main() {
   immutable(Foo)[] foos;
   foreach(i; 0..5) foos ~= new Foo;
	
   // compiles, typeof(bar1) == immutable(Foo)[]
   auto bar1 = array(foos.filter!(i => i.flag));
	
   // fails, expected typeof(bar2) == immutable(Foo)[]
   auto bar2 = array(foos.map!(i => i));
}

Error: cannot implicitly convert expression (arg) of type 
immutable(Foo) to test.Foo
Error: template instance 
std.conv.emplaceRef!(immutable(Foo)).emplaceRef!(immutable(Foo)) 
error instantiating
instantiated from here: array!(MapResult!(__lambda2, 
immutable(Foo)[]))
Nov 07 2014
next sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Fri, 07 Nov 2014 14:32:57 +0000
Jack Applegame via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

 import std.array;
 import std.algorithm;
=20
 class Foo {
 	bool flag;
 }
 void main() {
    immutable(Foo)[] foos;
    foreach(i; 0..5) foos ~=3D new Foo;
 =09
    // compiles, typeof(bar1) =3D=3D immutable(Foo)[]
    auto bar1 =3D array(foos.filter!(i =3D> i.flag));
 =09
    // fails, expected typeof(bar2) =3D=3D immutable(Foo)[]
    auto bar2 =3D array(foos.map!(i =3D> i));
 }
`map` cannot return range with immutable elements, 'cause they are obviously generated by program, and therefore aren't "immutable". i.e. map function can do alot of things which breaks immutability promise for range elements, and filter function cannot (as it doesn't return new element value). but map can return 'const' ranges, so changing your `foos` to 'const' will work.
Nov 07 2014
parent reply "anonymous" <anonymous example.com> writes:
On Friday, 7 November 2014 at 14:57:56 UTC, ketmar via
Digitalmars-d-learn wrote:
 `map` cannot return range with immutable elements, 'cause they 
 are
 obviously generated by program, and therefore aren't 
 "immutable".
That's not true. Runtime generated values can be immutable just fine. And it's std.array.array that's choking here, not map.
Nov 07 2014
parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Fri, 07 Nov 2014 15:18:24 +0000
anonymous via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 On Friday, 7 November 2014 at 14:57:56 UTC, ketmar via
 Digitalmars-d-learn wrote:
 `map` cannot return range with immutable elements, 'cause they=20
 are
 obviously generated by program, and therefore aren't=20
 "immutable".
=20 That's not true. Runtime generated values can be immutable just fine. And it's std.array.array that's choking here, not map.
ah, sorry, maybe i'm too tired now and talking nonsense. it can have a perfect sense for me, but still be nonsense. but don't blame me, it's gdc bug which makes gdc segfaults on my code, it eats all my brains.
Nov 07 2014
prev sibling next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Fri, 07 Nov 2014 14:32:57 +0000
Jack Applegame via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

ah, sorry, my bad, 'const' will not work to, for the same reason.
Nov 07 2014
prev sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 7 November 2014 at 14:33:00 UTC, Jack Applegame wrote:
 DMD64 D Compiler v2.066.1
 Why second call doesn't compile?

 import std.array;
 import std.algorithm;

 class Foo {
 	bool flag;
 }
 void main() {
   immutable(Foo)[] foos;
   foreach(i; 0..5) foos ~= new Foo;
 	
   // compiles, typeof(bar1) == immutable(Foo)[]
   auto bar1 = array(foos.filter!(i => i.flag));
 	
   // fails, expected typeof(bar2) == immutable(Foo)[]
   auto bar2 = array(foos.map!(i => i));
 }

 Error: cannot implicitly convert expression (arg) of type 
 immutable(Foo) to test.Foo
 Error: template instance 
 std.conv.emplaceRef!(immutable(Foo)).emplaceRef!(immutable(Foo)) 
 error instantiating
 instantiated from here: array!(MapResult!(__lambda2, 
 immutable(Foo)[]))
I'm pretty sure that should work. Please file a bug report. In the mean-time, either pre-allocate and std.algorithm.copy or - if you don't have the length - use std.array.appender and ~= the entire range in a single shot.
Nov 07 2014