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 "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
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 "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 "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
prev sibling next sibling parent "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
prev sibling next sibling 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):

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 "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

is disallowed. But I got enough answers, thanks to everybody!
Jun 14 2012