www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - initialization immutable array

reply "AntonSotov" <nepuvive rainmail.biz> writes:
DMD 2.065
I do not know much English. sorry.

need to initialize immutable array  "_items"
//-------------------------------------------------------
module main;
import std.stdio;

class Zond {
   this() {
     foreach (i; 1..4) {
       _items ~= i;  // is expected ERROR
     }
   }

   immutable(int[]) _items;
}

int main(string[] args)
{
   // create
   auto zond = new Zond();
   // test output
   foreach (it; zond._items) {
     writeln(it);
   }
   return 0;
}
//-------------------------------------------------------
this method does not work:
Error: field _items initializing not allowed in loops or after 
labels.

OK! is expected - I read in a book  Alexandrescu.

Make a small change, I add a nested function "addItem":
//-------------------------------------------------------
module main;
import std.stdio;

class Zond {
   this() {
     void addItem(in int value) {
       _items ~= value;  // OK ,  why?
     }

     foreach (i; 1..4) {
       addItem(i);
     }
   }

   immutable(int[]) _items;
}

int main(string[] args)
{
   // create
   auto zond = new Zond();
   // test output
   foreach (it; zond._items) {
     writeln(it);
   }
   return 0;
}
//-------------------------------------------------------
This method initialization works. why?
I do not understand the difference.
May 15 2014
next sibling parent "Yota" <yotaxp thatGoogleMailThing.com> writes:
On Thursday, 15 May 2014 at 16:13:59 UTC, AntonSotov wrote:
 DMD 2.065
 I do not know much English. sorry.

 need to initialize immutable array  "_items"
 //-------------------------------------------------------
 module main;
 import std.stdio;

 class Zond {
   this() {
     foreach (i; 1..4) {
       _items ~= i;  // is expected ERROR
     }
   }

   immutable(int[]) _items;
 }

You're only allowed to assign an immutable value in a constructor once, which is why it doesn't let you do so in a loop. As for the second example, that looks like a bug to me. Here are a couple ways to initialize the array: 1: this() { import std.exception : assumeUnique; int[] items; foreach (i; 1..4) { items ~= i; } _items = items.assumeUnique; } 2: this() { // The result of a pure function may be implicitly cast to immutable. _items = function() pure { int[] items; foreach (i; 1..4) { items ~= i; } return items; }(); } BTW, this would be better suited to the digitalmars.D.learn group.
May 15 2014
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 15 May 2014 12:13:58 -0400, AntonSotov <nepuvive rainmail.biz>  
wrote:

 DMD 2.065
 I do not know much English. sorry.

 need to initialize immutable array  "_items"
 //-------------------------------------------------------
 module main;
 import std.stdio;

 class Zond {
    this() {
      foreach (i; 1..4) {
        _items ~= i;  // is expected ERROR
      }
    }

    immutable(int[]) _items;
 }

 int main(string[] args)
 {
    // create
    auto zond = new Zond();
    // test output
    foreach (it; zond._items) {
      writeln(it);
    }
    return 0;
 }
 //-------------------------------------------------------
 this method does not work:
 Error: field _items initializing not allowed in loops or after labels.

Assign _items only once in the constructor. immutable(int)[] tmp; foreach(i; 1..4) tmp ~= i; _items = tmp;
 Make a small change, I add a nested function "addItem":
 //-------------------------------------------------------
 module main;
 import std.stdio;

 class Zond {
    this() {
      void addItem(in int value) {
        _items ~= value;  // OK ,  why?
      }

      foreach (i; 1..4) {
        addItem(i);
      }
    }

    immutable(int[]) _items;
 }

 int main(string[] args)
 {
    // create
    auto zond = new Zond();
    // test output
    foreach (it; zond._items) {
      writeln(it);
    }
    return 0;
 }
 //-------------------------------------------------------
 This method initialization works. why?
 I do not understand the difference.

This should not work IMO. -Steve
May 15 2014
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 05/15/2014 11:18 AM, AntonSotov wrote:

 if this is actually a bug - will be good if someone could register it.

Done: https://issues.dlang.org/show_bug.cgi?id=12749 Ali
May 15 2014
prev sibling next sibling parent "AntonSotov" <nepuvive rainmail.biz> writes:
On Thursday, 15 May 2014 at 17:15:50 UTC, Steven Schveighoffer 
wrote:
 Assign _items only once in the constructor.
 
 immutable(int)[] tmp;
 
 foreach(i; 1..4)
    tmp ~= i;
 
 _items = tmp;

thanks for example! On Thursday, 15 May 2014 at 17:15:50 UTC, Steven Schveighoffer wrote:
 This should not work IMO.

My second example compiles successfully and displays the correct result - that's why I became interested in why it works. you can compile yourself. On Thursday, 15 May 2014 at 16:58:04 UTC, Yota wrote:
 Here are a couple ways to initialize the array:

 1:
   this() {
     import std.exception : assumeUnique;
     int[] items;
     foreach (i; 1..4) {
       items ~= i;
     }
     _items = items.assumeUnique;
   }

 2:
   this() {
     // The result of a pure function may be implicitly cast to 
 immutable.
     _items = function() pure {
       int[] items;
       foreach (i; 1..4) {
         items ~= i;
       }
       return items;
     }();
   }

thanks for example! On Thursday, 15 May 2014 at 16:58:04 UTC, Yota wrote:
 As for the second example, that looks like a bug to me.

if this is actually a bug - will be good if someone could register it.
May 15 2014
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 15 May 2014 14:18:03 -0400, AntonSotov <nepuvive rainmail.biz>  
wrote:

 On Thursday, 15 May 2014 at 17:15:50 UTC, Steven Schveighoffer wrote:
 Assign _items only once in the constructor.
  immutable(int)[] tmp;
  foreach(i; 1..4)
    tmp ~= i;
  _items = tmp;

thanks for example! On Thursday, 15 May 2014 at 17:15:50 UTC, Steven Schveighoffer wrote:
 This should not work IMO.

My second example compiles successfully and displays the correct result - that's why I became interested in why it works. you can compile yourself.

I didn't speak clearly, I understand that it currently "works", but that is a bug. It shouldn't work. -Steve
May 15 2014
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 15/05/14 18:13, AntonSotov wrote:
 DMD 2.065
 I do not know much English. sorry.

 need to initialize immutable array  "_items"
 //-------------------------------------------------------
 module main;
 import std.stdio;

 class Zond {
    this() {
      foreach (i; 1..4) {
        _items ~= i;  // is expected ERROR
      }
    }

    immutable(int[]) _items;

This might not bet what you were asking for, but alternativly you could use "iota": import std.algorithm; import std.range; immutable(int[]) _items = 1.iota(4).array; -- /Jacob Carlborg
May 15 2014
parent Jacob Carlborg <doob me.com> writes:
On 16/05/14 10:32, monarch_dodra wrote:

 UFCS iota :puke:

Yeah, it would make more sense if it would be called "upto": 1.upto(4) -- /Jacob Carlborg
May 16 2014
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 16 May 2014 at 06:37:30 UTC, Jacob Carlborg wrote:
 import std.algorithm;
 import std.range;

 immutable(int[]) _items = 1.iota(4).array;

UFCS iota :puke:
May 16 2014
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
monarch_dodra:

 UFCS iota :puke:

I think UFCS iota is acceptable when it has only one argument: myArray.length.iota... Bye, bearophile
May 16 2014
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 16 May 2014 at 08:43:31 UTC, bearophile wrote:
 monarch_dodra:

 UFCS iota :puke:

I think UFCS iota is acceptable when it has only one argument: myArray.length.iota... Bye, bearophile

My gripe is how "incompatible" 1-arg and 2-arg iota is w.r.t. UFCS: 0.iota(4); 4.iota(); That's also why I've stopped using "writeln()" as UFCS: It "looks" convenient at first, but then you want to turn those "writeln" into "writefln", and that's when things don't go according to plan...
May 16 2014
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
monarch_dodra:

 That's also why I've stopped using "writeln()" as UFCS: It 
 "looks" convenient at first, but then you want to turn those 
 "writeln" into "writefln", and that's when things don't go 
 according to plan...

Yes, I understand. If you want some ugly code you can use std.functional.binaryReverseArgs: alias flip = binaryReverseArgs; myRange.flip!writefln("%s") bye, bearophile
May 16 2014