www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Create an array with immutable elements

reply "Roman D. Boiko" <rb d-coding.com> writes:
immutable struct Node{ string s; }
Node[] f()
{
   Node[] arr = ...?
   return arr;
}

How to fill an array, if its elements are immutable? I want to 
assign values calculated by some function.
Jun 14 2012
next sibling parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Thursday, 14 June 2012 at 23:57:36 UTC, Roman D. Boiko wrote:
 immutable struct Node{ string s; }
 Node[] f()
 {
   Node[] arr = ...?
   return arr;
 }

 How to fill an array, if its elements are immutable? I want to 
 assign values calculated by some function.

I recall this in TDPL, you can append to an array as it doesn't change it's contents, only the range the array holds... So... Node[] f() { immutable(Node)[] arr; arr ~= Node("something"); //should work? return arr; }
Jun 14 2012
parent "Roman D. Boiko" <rb d-coding.com> writes:
On Friday, 15 June 2012 at 00:08:33 UTC, Era Scarecrow wrote:
 On Thursday, 14 June 2012 at 23:57:36 UTC, Roman D. Boiko wrote:
 immutable struct Node{ string s; }
 Node[] f()
 {
  Node[] arr = ...?
  return arr;
 }

 How to fill an array, if its elements are immutable? I want to 
 assign values calculated by some function.

I recall this in TDPL, you can append to an array as it doesn't change it's contents, only the range the array holds... So... Node[] f() { immutable(Node)[] arr; arr ~= Node("something"); //should work? return arr; }

That might be inefficient for large arrays. (In my case, arrays are small.) Would array appender work here? I guess it should.
Jun 14 2012
prev sibling next sibling parent "Roman D. Boiko" <rb d-coding.com> writes:
On Thursday, 14 June 2012 at 23:57:36 UTC, Roman D. Boiko wrote:
 immutable struct Node{ string s; }
 Node[] f()
 {
   Node[] arr = ...?
   return arr;
 }

 How to fill an array, if its elements are immutable? I want to 
 assign values calculated by some function.

More specifically, given auto names = ["ab", "c", "def"] ~ getMoreNames(); retrieve [Node("ab"), Node("abc"), Node("abcdef"), ...] where Node is an immutable struct created dynamically, possibly with usage of some accumulating variable (in this case, a string concatenating previous values). But an answer to the first question should be enough, this example is just for clarity.
Jun 14 2012
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Roman D. Boiko:

 immutable struct Node{ string s; }
 Node[] f()
 {
   Node[] arr = ...?
   return arr;
 }

 How to fill an array, if its elements are immutable? I want to 
 assign values calculated by some function.

In general sometimes it's not easy to build immutable data structures. In D there are several ways to do something similar to what you ask, some alternatives (maybe there are more possibilities): ------------------------------------- immutable struct Node { string s; } string bar(in int x) pure nothrow in { assert(x >= 0 && x <= 9); } body { return "hello" ~ cast(char)(x + '0'); } Node[] foo() { Node[] arr; enum size_t N = 5; arr.reserve(N); foreach (i; 0 .. N) arr ~= Node(bar(i)); return arr; } void main() { import std.stdio; //writeln(foo()); // try this! writeln(foo()[0]); } ------------------------------------- import std.exception; struct Node { string s; } immutable(Node)[] foo() { enum size_t N = 5; auto arr = new Node[N]; foreach (i; 0 .. N) arr[i] = Node("hello" ~ cast(char)(i + '0')); return assumeUnique(arr); } void main() { import std.stdio; writeln(foo()[0]); } ------------------------------------- struct Node { string s; } immutable(Node)[] foo() pure nothrow { enum size_t N = 5; auto arr = new Node[N]; foreach (i; 0 .. N) arr[i] = Node("hello" ~ cast(char)(i + '0')); return arr; } void main() { import std.stdio; writeln(foo()[0]); } ------------------------------------- struct Node { string s; } Node[] foo() pure nothrow { enum size_t N = 5; auto arr = new Node[N]; foreach (i; 0 .. N) arr[i] = Node("hello" ~ cast(char)(i + '0')); return arr; } void main() { import std.stdio; immutable result = foo(); writeln(result[0]); } Bye, bearophile
Jun 14 2012
parent "Roman D. Boiko" <rb d-coding.com> writes:
On Friday, 15 June 2012 at 00:14:11 UTC, bearophile wrote:
 Roman D. Boiko:

 immutable struct Node{ string s; }
 Node[] f()
 {
  Node[] arr = ...?
  return arr;
 }

 How to fill an array, if its elements are immutable? I want to 
 assign values calculated by some function.

In general sometimes it's not easy to build immutable data structures. In D there are several ways to do something similar to what you ask, some alternatives (maybe there are more possibilities):

Only the first example works, because assignment to immutable elements of array is not allowed. But thanks for reminding me that I can reserve desired number of elements :) This makes the first example a perfect solution for me.
Jun 14 2012
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, June 15, 2012 01:57:35 Roman D. Boiko wrote:
 immutable struct Node{ string s; }
 Node[] f()
 {
 Node[] arr = ...?
 return arr;
 }
 
 How to fill an array, if its elements are immutable? I want to
 assign values calculated by some function.

There are 3 options that I know of: 1. Create an empty array and append the elements to it. 2. Use Appender (which will be more efficient than #1). e.g. auto app = appender!(immutable Node[])(); app.put(value1); app.put(value2); //... auto arr = app.data; 3. Create the array as mutable and then cast it to immutable. auto arr = new Node[](length); arr[0] = value1; arr[1] = value2; //.. auto immArr = cast(immutable(Node)[])arr; or better auto immArr = assumeUnique(arr); though that will make the whole array immutable rather than just the Nodes - though that can be fixed by doing auto immArr = assumeUnique(arr)[]; since array slices are tail-const. - Jonathan M Davis
Jun 14 2012
parent "Roman D. Boiko" <rb d-coding.com> writes:
On Friday, 15 June 2012 at 00:18:23 UTC, Jonathan M Davis wrote:
 On Friday, June 15, 2012 01:57:35 Roman D. Boiko wrote:
 immutable struct Node{ string s; }
 Node[] f()
 {
 Node[] arr = ...?
 return arr;
 }
 
 How to fill an array, if its elements are immutable? I want to
 assign values calculated by some function.

There are 3 options that I know of: 1. Create an empty array and append the elements to it. 2. Use Appender (which will be more efficient than #1). e.g. auto app = appender!(immutable Node[])(); app.put(value1); app.put(value2); //... auto arr = app.data; 3. Create the array as mutable and then cast it to immutable. auto arr = new Node[](length); arr[0] = value1; arr[1] = value2; //.. auto immArr = cast(immutable(Node)[])arr; or better auto immArr = assumeUnique(arr); though that will make the whole array immutable rather than just the Nodes - though that can be fixed by doing auto immArr = assumeUnique(arr)[]; since array slices are tail-const. - Jonathan M Davis

Please note that type of Node is immutable. So the third option is disallowed. But I got enough answers, thanks to everybody!
Jun 14 2012