Re: const after initialization / pointers, references and values

2014-08-22 Thread Vicente via Digitalmars-d

First of all thanks for your replies, they are useful.

@Philippe:
A pure function is ok for initializing default_nodes but not 
for nodes because a pure function can't read a file.
The static this has the problem it needs know the initializer 
at compile time but I wanted to choose the initializer at run 
time.
I know default_nodes can be changed to immutable, but then it 
will require an explicit cast to remove the immutability.

The final class may be a good point, I'll try this one.

@Jakob:
Thank you, but I'll go with Philippe's suggestion.

@Wyatt:
Certainly ref parameters help a lot, but I'm trying to get a 
Node by returning (a reference to) it. Does the ref keyword 
apply to the return type?

Next time I'll post to D.learn, sorry for misplacing my question.

Regards,
  Vicente.


Re: const after initialization / pointers, references and values

2014-08-22 Thread Vicente via Digitalmars-d

Indeed the ref can be applied to the return type:
http://dlang.org/function.html#ref-functions

So, does the following code copy any data from nodes?
If that is the case this solution avoids the class storage, 
avoids pointers and nodes is encapsulated as read-only, that's 
great.
The program I'm working on is still incomplete, so I still can't 
benchmark it to compare with all proposed solutions.


@safe:
import std.stdio;
import std.string;

struct Node {
Node[] block;
uint num = 0;
};

immutable uint LAST = -1;
Node[] default_nodes = [
{num:3},
{block:[{num:4},{num:6},{block:[{num:5},{num:7}]}]},
// ...
{num:LAST},
];

class NodeProvider{
// change to const after constructor
private Node[] nodes;

private void parse_file(char[] file_name){
// initialize nodes from file
for(auto i=0; i3; i++){
nodes.length++;
nodes[$-1].num=i;
}
nodes.length++;
nodes[$-1].num=LAST;
}

this(){
nodes = default_nodes;
}
this(char[] file_name){
parse_file(file_name);
}

ref const(Node) get_node(const uint index){
return nodes[index];
}
}

string NodetoString(ref const(Node) n){
string str = format(%u{ , n.num);
foreach(b;n.block)
str ~= NodetoString(b);
str ~= } ;
return str;
}

@system: // for writeln
int main(char[][] args){
NodeProvider np;
uint i;

if(args.length==2)
np = new NodeProvider(args[1]);
else
np = new NodeProvider();

for(i=0;;i++){
const(Node) node = np.get_node(i);
if(node.num==LAST)
break;
writeln(NodetoString(node));
}
return 0;
}


Re: const after initialization / pointers, references and values

2014-08-22 Thread Vicente via Digitalmars-d

On Friday, 22 August 2014 at 20:12:39 UTC, Wyatt wrote:
I poked it a bit and came out with this.  I _think_ it's 
working as expected:

...

auto ref opSlice(){return nodes[];};

...

-Wyatt


Assuming it's working as expected, that is exactly what I was 
looking for!
But the following code shows that at some point data gets copied. 
By the way, neither works what I've posted previously.

In any case, thank you very much Wyatt.

Regards,
  Vicente.

@safe:
import std.stdio;
import std.string;

struct Node { Node[] block; uint num = 0; };
/* immutable */ Node[] default_nodes = [ {num:3}, 
{block:[{num:4}]}, {num:6} ];


class NodeProvider{
private /* const */ Node[] nodes;
private Node[] tmp_nodes;

private void parse_file(char[] file_name){
tmp_nodes.length=1; tmp_nodes[0].num=5;
}

this(){ nodes = default_nodes; }
this(char[] file_name){
parse_file(file_name);
nodes = tmp_nodes;
}

auto ref opSlice(){return nodes[];};
}

@system: // for writeln
int main(char[][] args){
NodeProvider np;

if(args.length==2) np = new NodeProvider(args[1]);
else   np = new NodeProvider();

// if they are real references this will modify the source data
foreach(node_ref; np) node_ref.num = 101;
// and will print all 101
foreach(node_ref; np) writeln(node_ref.num);
// but it prints unmodified 3, 0 and 6

return 0;
}


Re: const after initialization / pointers, references and values

2014-08-22 Thread Vicente via Digitalmars-d

If the foreach loop is replaced by:
foreach(ref node_ref; np)
Then it works like a charm!


const after initialization / pointers, references and values

2014-08-20 Thread Vicente via Digitalmars-d

Hello,
I have some questions on how to do a few things in D.
Below is an example code on which the questions are based.

I need read access to a big and complex (i.e.: nested) data
structure of type Node.
But first it needs to be initialized. That can be done with a
default initializer or from a file.
After initialization there is no need to modify the data anymore.
My first question is: can the data be changed to const once
initialized?
if no, is there any alternative to acomplish that?
note that encapsulating into a class with only get_* methods
does not help because the get_node method returns a pointer to
the data
Related to that, how can the default initializer be changed to
immutable?

The second question is related to pointers, references and values
I know that structs by default use value semantics, but as data
is large I want to avoid data copying.
But I would like to avoid use of pointers, so, is there a way of
using reference semantics in the example code?
Maybe is as simple as changing from struct Node to class
Node, but seems intuitive that classes carry more overhead than
structs.
How much overhead carries a class in comparison to a struct?

Regards,
   Vicente.


import std.stdio;
import std.string;

// struct or class
struct Node {
Node[] block;
uint num = 0;
};

// static immutable
Node[] default_nodes = [
{num:3},
{block:[{num:4},{num:6},{block:[{num:5},{num:7}]}]},
// ...
];

class NodeProvider{
// change to const after constructor
private Node[] nodes;

private void parse_file(char[] file_name){
// initialize nodes from file
for(auto i=0; i3; i++){
nodes.length++;
nodes[$-1].num=i;
}
}

this(){
nodes = default_nodes;
}
this(char[] file_name){
parse_file(file_name);
}

Node* get_node(const uint index){
if(index=nodes.length)
return null;
return (nodes[index]);
}
}

string NodetoString(Node n){
string str = format(%u{ , n.num);
foreach(b;n.block)
str ~= NodetoString(b);
str ~= } ;
return str;
}

int main(char[][] args){
NodeProvider np;
Node* node_ptr;
uint i;

if(args.length==2)
np = new NodeProvider(args[1]);
else
np = new NodeProvider();

i = 0;
while((node_ptr=np.get_node(i))!=null){
writeln(NodetoString(*node_ptr));
i++;
}
return 0;
}