lazy construction of an immutable object

2014-07-15 Thread Puming via Digitalmars-d-learn

Hi,

I'd like to use immutable data, but instead of a one time 
constructor, I would like to `build` the data lazily, by setting 
its fields separately.


In java version of protocol-buffer, there is a pattern for this 
mechanism:


1. Every data class in protobuf is immutable.
2. Each data class is companioned by a Builder class, with the 
same field of the immutable data class.
3. To create a data object, first create a Builder, then set the 
fields when ever you want.


I want to emulate this process, but without needing to create two 
classes for one data class (protobuff does this by a separate 
code generating phase to generate both classes from a data format 
file).


What is the idiomatic approach to do this in D?

if I define a class with immutable fields, like

```d
class A {
  immutable int id;
  immutable B b;
}
```

should I use a template to generate the companion Builder class, 
or is there another aproach?




Re: lazy construction of an immutable object

2014-07-15 Thread Puming via Digitalmars-d-learn
I found another way to do this, namely first create a class that 
is mutable, then cast it to an immutable object before using it.


```d

class A {
int a;
B b;
this(int a, int b)
{
this.a = a;
this.b = new B(b);
}
}


class B {
int b;
this(int b)
{
this.b = b;
}
}

@property immutable(T) freeze(T)(T obj)
{
return cast(immutable(T))(obj);
}

void main()
{

immutable c = new A(3, 4).freeze;
	c.b.b = 5; // Error: can only initialize const member b inside 
constructor

writeln(c.b.b)
}
```

But the draw back is that you can't garanteed that the mutable 
object is never used.



On Tuesday, 15 July 2014 at 10:39:42 UTC, Puming wrote:

Hi,

I'd like to use immutable data, but instead of a one time 
constructor, I would like to `build` the data lazily, by 
setting its fields separately.


In java version of protocol-buffer, there is a pattern for this 
mechanism:


1. Every data class in protobuf is immutable.
2. Each data class is companioned by a Builder class, with the 
same field of the immutable data class.
3. To create a data object, first create a Builder, then set 
the fields when ever you want.


I want to emulate this process, but without needing to create 
two classes for one data class (protobuff does this by a 
separate code generating phase to generate both classes from a 
data format file).


What is the idiomatic approach to do this in D?

if I define a class with immutable fields, like

```d
class A {
  immutable int id;
  immutable B b;
}
```

should I use a template to generate the companion Builder 
class, or is there another aproach?




Re: lazy construction of an immutable object

2014-07-15 Thread Ali Çehreli via Digitalmars-d-learn

On 07/15/2014 05:20 AM, Puming wrote:

I found another way to do this, namely first create a class that is
mutable, then cast it to an immutable object before using it.

```d

class A {
 int a;
 B b;
 this(int a, int b)
 {
 this.a = a;
 this.b = new B(b);
 }
}


class B {
 int b;
 this(int b)
 {
 this.b = b;
 }
}

@property immutable(T) freeze(T)(T obj)
{
 return cast(immutable(T))(obj);
}

void main()
{

 immutable c = new A(3, 4).freeze;
 c.b.b = 5; // Error: can only initialize const member b inside
constructor
 writeln(c.b.b)
}
```

But the draw back is that you can't garanteed that the mutable object is
never used.


Also consider: A pure function's return value can implicitly be 
converted to immutable.


class A
{
int x;
int y;

this (int x) pure
{
this. x = x;
}
}

pure A makeA(int x)// -- returns mutable
{
auto a = new A(x);

// ...
// Set a member later on:
a.y = 42;

return a;
}

void main()
{
immutable imm = makeA(1);// -- works
}

Ali



Re: lazy construction of an immutable object

2014-07-15 Thread Puming via Digitalmars-d-learn

On Tuesday, 15 July 2014 at 13:59:24 UTC, Ali Çehreli wrote:

On 07/15/2014 05:20 AM, Puming wrote:
I found another way to do this, namely first create a class 
that is

mutable, then cast it to an immutable object before using it.

```d

class A {
int a;
B b;
this(int a, int b)
{
this.a = a;
this.b = new B(b);
}
}


class B {
int b;
this(int b)
{
this.b = b;
}
}

@property immutable(T) freeze(T)(T obj)
{
return cast(immutable(T))(obj);
}

void main()
{

immutable c = new A(3, 4).freeze;
c.b.b = 5; // Error: can only initialize const member b 
inside

constructor
writeln(c.b.b)
}
```

But the draw back is that you can't garanteed that the mutable 
object is

never used.


Also consider: A pure function's return value can implicitly be 
converted to immutable.


class A
{
int x;
int y;

this (int x) pure
{
this. x = x;
}
}

pure A makeA(int x)// -- returns mutable
{
auto a = new A(x);

// ...
// Set a member later on:
a.y = 42;

return a;
}

void main()
{
immutable imm = makeA(1);// -- works
}

Ali


wow, that's interesting :-) Is it the idiomatic approach to 
initiate immutable objects lazily? Or do people use data class 
with immutable fields and generate a companion builder class at 
compile time?





Re: lazy construction of an immutable object

2014-07-15 Thread Meta via Digitalmars-d-learn

On Tuesday, 15 July 2014 at 15:48:10 UTC, Puming wrote:
wow, that's interesting :-) Is it the idiomatic approach to 
initiate immutable objects lazily? Or do people use data class 
with immutable fields and generate a companion builder class at 
compile time?


There's no real idiomatic approach, I think, because this is 
somewhat unexplored territory. I'd say constructing the object 
inside a pure method so it can be implicitly cast to immutable is 
more typesafe, but if you're storing the immutable reference to 
the object in a class or struct, it can only be initialized in 
that class's/struct's constructor. So the following isn't 
possible:


struct Test
{
immutable(int*) n;

private int* getPtr() pure
{
int* n = new int;
*n = 42;

return n;
}

public void initialize() pure
{
n = getPtr();
}
}

void main()
{
auto t = new Test();
test.initialize();
}


Re: lazy construction of an immutable object

2014-07-15 Thread Puming via Digitalmars-d-learn

On Tuesday, 15 July 2014 at 17:09:04 UTC, Meta wrote:

On Tuesday, 15 July 2014 at 15:48:10 UTC, Puming wrote:
wow, that's interesting :-) Is it the idiomatic approach to 
initiate immutable objects lazily? Or do people use data class 
with immutable fields and generate a companion builder class 
at compile time?


There's no real idiomatic approach, I think, because this is 
somewhat unexplored territory. I'd say constructing the object 
inside a pure method so it can be implicitly cast to immutable 
is more typesafe, but if you're storing the immutable reference 
to the object in a class or struct, it can only be initialized 
in that class's/struct's constructor. So the following isn't 
possible:


struct Test
{
immutable(int*) n;

private int* getPtr() pure
{
int* n = new int;
*n = 42;

return n;
}

public void initialize() pure
{
n = getPtr();
}
}

void main()
{
auto t = new Test();
test.initialize();
}


So this means that the pure method approach should also be 
transitive: the containing class should also be mutable (having 
the desired immutable object as a mutable field) and later freeze 
itself.


If there is a complex hierarchy of objects, there are three 
strategies:


1. define all classes and fields mutable, and use immutable value 
in the business logic code. This would work, but lose the 
compilers help with checking immutability in all conditions. For 
example, you coud modify the mutable reference if it is leaked.
2. define all classes and fields immutable, and only use 
constructor to eagerly create objects and there fields. This is 
the most strict, but will incur some inconvenience in 
asynchronous environments, where not all parts of the data is 
available at start.
3. define all classes and use template magic to generate 
companion builders just like protobuffer does. But that would be 
complicated and I don't know how to do it. Do you have any 
suggestion for this approach?





Re: lazy construction of an immutable object

2014-07-15 Thread Jason den Dulk via Digitalmars-d-learn

On Tuesday, 15 July 2014 at 12:20:57 UTC, Puming wrote:


@property immutable(T) freeze(T)(T obj)
{
return cast(immutable(T))(obj);
}



What is the idiomatic approach to do this in D?


There is a Phobos function std.exception.assumeUnique which 
performs this for arrays. According to the docs, it does what 
'freeze' does, and is considered idiomatic.


But the draw back is that you can't garanteed that the mutable 
object is never used.


I got the impression that assumeUnique has the same problem.

Regards