Thread overview
std.array.array and immutable elements
Nov 07, 2014
Jack Applegame
Nov 07, 2014
ketmar
Nov 07, 2014
anonymous
Nov 07, 2014
ketmar
Nov 07, 2014
ketmar
Nov 07, 2014
John Colvin
November 07, 2014
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)[]))
November 07, 2014
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;
> 
> 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));
> }
`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.


November 07, 2014
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.


November 07, 2014
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.
November 07, 2014
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
> > 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.
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.


November 07, 2014
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.