Re: Immutable objects and constructor ?

2016-05-21 Thread chmike via Digitalmars-d-learn

On Saturday, 21 May 2016 at 08:24:19 UTC, Ali Çehreli wrote:

On 05/21/2016 01:07 AM, chmike wrote:
> Unfortunately it is not possible to write this
>
> import std.typecons;
> class Info{...}
> rebindable!Info x;

You have a capitalization typo. Rebindable is a type template, 
rebindable is a function template.


import std.typecons;
class Info{}

void main() {
auto x = rebindable(new immutable(Info)());
pragma(msg, typeof(x));

auto y = Rebindable!(immutable(Info))(new Info());
pragma(msg, typeof(y));
}

Ali


Thank you. I'll start a new thread with the subject "problems 
with Rebindable".
See 
https://forum.dlang.org/post/bprfdptcvzzkfzxlh...@forum.dlang.org


Re: Immutable objects and constructor ?

2016-05-21 Thread Ali Çehreli via Digitalmars-d-learn

On 05/21/2016 01:07 AM, chmike wrote:
> Unfortunately it is not possible to write this
>
> import std.typecons;
> class Info{...}
> rebindable!Info x;

You have a capitalization typo. Rebindable is a type template, 
rebindable is a function template.


import std.typecons;
class Info{}

void main() {
auto x = rebindable(new immutable(Info)());
pragma(msg, typeof(x));

auto y = Rebindable!(immutable(Info))(new Info());
pragma(msg, typeof(y));
}

Ali



Re: Immutable objects and constructor ?

2016-05-21 Thread chmike via Digitalmars-d-learn
Since I'm trying to implement a flyweight pattern, the opEqual 
need only comparision of reference in my case.


By the way, what operation is the switch performing ? OpEqual or 
is ?


Re: Immutable objects and constructor ?

2016-05-21 Thread chmike via Digitalmars-d-learn

Unfortunately it is not possible to write this

import std.typecons;
class Info{...}
rebindable!Info x;

I get the following error message

source/app.d(11,3): Error: template std.typecons.rebindable 
matches more than one template declaration:
/usr/include/dmd/phobos/std/typecons.d(1675,14): 
rebindable(T)(T obj) if (is(T == class) || is(T == interface) || 
isDynamicArray!T || isAssociativeArray!T)

and
/usr/include/dmd/phobos/std/typecons.d(1694,14): 
rebindable(T)(Rebindable!T obj)



This would have been equivalent to define a mutable reference to 
an object of type Info and allow me to write this


alias rebindable!Info InfoR;
InfoR x;

Unfortunately I didn't manage to get something compiling with 
rebindable. I don't understand how I'm supposed to use it.



Note that I'm designing a library that I would like intuitive to 
use. Hacking around the problem won't cut it.


I need a type defining a mutable reference to an immutable 
object. Rebindable doesn't give me that apparently.


I need something allowing me to write this

interface Info {...}
class MyInfos {
static class Obj : Info {...}
static immutable Obj one = new immutable Obj(...);
}

mutableObjectRef!Info x1, x2;
assert(x1 is null);
assert(x1 == null);
x1 = MyInfos.one;
assert(x1 is MyInfos.one);
assert(x1 == MyInfos.one);
x2 = x1;

switch(x1){
case MyInfos.one: ... ;
default:...;
}

x1 must have the semantic of an object reference, support 
polymorphism, allowing to down or up cast and of course access 
immutable members and methods.
MyInfos.one is an object reference that I shouldn't be allowed to 
modify. I can't use a function because it needs the value 
semantic so I can use it as a case argument in a switch.


It doesn't seam that this is what rebind provides. It looks like 
mutableObjectRef should be a templated struct. But I'm not 
experienced enough in D to implement it. I don't know if its only 
possible.









Re: Immutable objects and constructor ?

2016-05-20 Thread Mike Parker via Digitalmars-d-learn

On Friday, 20 May 2016 at 16:09:54 UTC, chmike wrote:


This is confusing and frustrating. In C++ we can write
MyInfos {
   . . .
   // one is a constant pointer to a constant object of type Obj
   Obj const * const one;
   . . .
}

And in main()

Info const * x1 = MyInfos.one;

x1 i a modifiable pointer to a constant object of type Info.

Is this possible in D ? I couldn't find how to do that.


I should have addressed this above. This is another of the those 
things that will bite you if you are thinking in C++ when writing 
D. Classes in D are references types, so right out of the gate 
they can not be treated as C++ classes. You absolutely can have 
modifiable pointers to const and immutable data with built in 
types and structs, but not with classes. Always think of 
const(classref) as const(class*). There is no such thing as 
const(class)* in D.


Re: Immutable objects and constructor ?

2016-05-20 Thread Mike Parker via Digitalmars-d-learn

On Friday, 20 May 2016 at 16:09:54 UTC, chmike wrote:



But I now met another error in my main(). I can't assign the 
immutable object to a mutable reference.


Info x1 = MyInfos.one;

Is it possible to define a mutable reference to an immutable 
instance ? 


This is confusing and frustrating. In C++ we can write
MyInfos {
   . . .
   // one is a constant pointer to a constant object of type Obj
   Obj const * const one;
   . . .
}



I strongly advise you put C++ out of your head when programming D 
and try to come at it as if you have never seen C++. Otherwise, 
you will just keep getting frustrated. D is a different language 
and, while some C++ idioms may work just fine, others do not and 
cannot.


Consider this:

immutable(int*) ifoo;

Because the * is inside the parens in the declaration of ifoo, we 
are saying that we never want the pointer to be reassigned. The 
compiler is free to behave as if that is true and that ifoo will 
always point to the same address. It might make certain 
optimizations based on that guarantee that might not otherwise be 
possible. The same is true if you replace immutable with const in 
this particular declaration. If you somehow manage to circumvent 
that guarantee, then you are breaking the compiler's expectations 
and entering the realm of undefined behavior. You can think of an 
immutable class reference as being an immutable pointer like ifoo.


C++ has no such guarantees. The compiler is not free to make the 
same assumptions D can make. If D allowed you to do what C++ 
does, then D compilers would be in the same boat. This is one of 
the reasons why you can't expect D code to behave like C++ code 
in every case, no matter how similar things look on the surface.





Re: Immutable objects and constructor ?

2016-05-20 Thread Mike Parker via Digitalmars-d-learn

On Friday, 20 May 2016 at 20:30:22 UTC, chmike wrote:



I'm a bit surprized that the language doesn't support this. We 
have immutable strings that can be assigned to different 
variables. Why couldn't we do the same with objects ?


Consider this:

immutable(char)[] str;

Here, the array elements of str are immutable, i.e. you cannot do 
this:


str[0] = 's'

However, the array reference itself is mutable, so you can freely 
assign array references around. This is what string is aliased to.


To prevent the array reference from being assigned:

immutable(char[]) str;

Now trying to assign another string to str will produce a 
compiler error.


With arrays and pointers, we distinguish between the data and the 
reference. With classes, we do not; there is only the reference.




Re: Immutable objects and constructor ?

2016-05-20 Thread Jonathan M Davis via Digitalmars-d-learn
On Friday, May 20, 2016 20:30:22 chmike via Digitalmars-d-learn wrote:
> On Friday, 20 May 2016 at 17:35:01 UTC, Kagamin wrote:
> > On Friday, 20 May 2016 at 16:09:54 UTC, chmike wrote:
> >> But I now met another error in my main(). I can't assign the
> >> immutable object to a mutable reference.
> >>
> >> Info x1 = MyInfos.one;
> >>
> >> Is it possible to define a mutable reference to an immutable
> >> instance ?
> >
> > Sort of possible with a library solution:
> >
> > import std.typecons;
> > auto x1 = rebindable(MyInfos.one);
>
> I'm a bit surprized that the language doesn't support this. We
> have immutable strings that can be assigned to different
> variables. Why couldn't we do the same with objects ?

It has to do with the fact that the type system does not differentiate
between classes and references to class objects. When you type

Object o;

that's a reference to a class, not actually a class object, and the same
goes for every use of a class.  So, while you can have

const(int)* ptr;

and the compiler understands that, the compiler doesn't have an
understanding of the separation of an Object and a reference to an Object,
so not only is there no way to represent it syntactically, the compiler
can't currently represent it semantically either. This is at least partially
a result of making it so that classes inherently live on the heap.

It's certainly possible to change it so that we have a way to have
tail-const references to classes and so that Rebindable is then unnecessary,
but Walter and Andrei don't think that it's worth it, so it hasn't happened.
And while Rebindable is kind of ugly, it works just fine. So, the lack of
tail-const for classes in the language hasn't really been a blocker for
anything, just kind of ugly.

> This rebindable is not user friendly.
> I really wish the user could write this
>
> Info x = MyInfos.one;
>
> I may achieve this if Info is defined as a struct with a single
> member defined as rebindable.

Well, as long as you're dealing with local variables, you can use auto
rather than typing the type explicitly, and then you don't need to
explicitly use Rebindable, though you generally would for function
parameters and member variables. But while typing Rebindable is a bit ugly,
it's basically just a bit more verbose than what you'd get if it were built
in. Right now you have

Rebindable!Info info;

whereas if it were buit in, you'd probably get something like

tail_const(Info) info;

or I think that someone suggested something like

const(ref) Info info;

And both of those are about as verbose as Rebindable is. So, they wouldn't
save us much. So, sure, it would be nice if tail-const classes were built
into the language, but we don't seem to be losing much by not having them.
If someone could come up with why the lack of tail-const classes were a
major roadblocker somehow, then maybe Walter could be convinced to alter the
language, but you'd need a very solid reason as to why Rebindable doesn't
cut it, and thinking that it's a bit ugly isn't going to be enough.

- Jonathan M Davis



Re: Immutable objects and constructor ?

2016-05-20 Thread chmike via Digitalmars-d-learn

On Friday, 20 May 2016 at 17:35:01 UTC, Kagamin wrote:

On Friday, 20 May 2016 at 16:09:54 UTC, chmike wrote:
But I now met another error in my main(). I can't assign the 
immutable object to a mutable reference.


Info x1 = MyInfos.one;

Is it possible to define a mutable reference to an immutable 
instance ? 


Sort of possible with a library solution:

import std.typecons;
auto x1 = rebindable(MyInfos.one);


I'm a bit surprized that the language doesn't support this. We 
have immutable strings that can be assigned to different 
variables. Why couldn't we do the same with objects ?


This rebindable is not user friendly.
I really wish the user could write this

Info x = MyInfos.one;

I may achieve this if Info is defined as a struct with a single 
member defined as rebindable.





Re: Immutable objects and constructor ?

2016-05-20 Thread Kagamin via Digitalmars-d-learn

On Friday, 20 May 2016 at 16:09:54 UTC, chmike wrote:
But I now met another error in my main(). I can't assign the 
immutable object to a mutable reference.


Info x1 = MyInfos.one;

Is it possible to define a mutable reference to an immutable 
instance ? 


Sort of possible with a library solution:

import std.typecons;
auto x1 = rebindable(MyInfos.one);


Re: Immutable objects and constructor ?

2016-05-20 Thread chmike via Digitalmars-d-learn

On Friday, 20 May 2016 at 15:43:28 UTC, Marc Schütz wrote:



It looks like your don't actually need `Obj` to be a real 
nested class. Try declaring it as `static Obj : Info { }`. This 
should work if `Obj`'s methods don't need access to `MyInfo`'s 
non-static members.


That worked great. Thank you.

The only problem left is how I can get mutable references to 
immutable objects.




Re: Immutable objects and constructor ?

2016-05-20 Thread chmike via Digitalmars-d-learn
I solved the problem by moving the class Obj definition out of 
the class MyInfo.
I still don't understand why I had to do that. In C++ this would 
work without problem.


I now have

interface Info {. . .}

class Obj : Info {. . .}

class MyInfos
{
. . .
static immutable Obj one = new immutable Obj(...);
static immutable Obj two = new immutable Obj(...);
. . .
}

This now compiles without a peep.

But I now met another error in my main(). I can't assign the 
immutable object to a mutable reference.


Info x1 = MyInfos.one;

Is it possible to define a mutable reference to an immutable 
instance ? 


This is confusing and frustrating. In C++ we can write
MyInfos {
   . . .
   // one is a constant pointer to a constant object of type Obj
   Obj const * const one;
   . . .
}

And in main()

Info const * x1 = MyInfos.one;

x1 i a modifiable pointer to a constant object of type Info.

Is this possible in D ? I couldn't find how to do that.




Re: Immutable objects and constructor ?

2016-05-20 Thread Marc Schütz via Digitalmars-d-learn

On Friday, 20 May 2016 at 15:07:53 UTC, chmike wrote:
The error message is gone, but I now have another compilation 
error message I don't understand.


This is what I have in fact

interface Info { . . . }

class MyInfos {
   . . .
protected:
   class Obj : Info
   {
   . . .
   }

public:
   static immutable Obj one = new immutable Obj(...);
   static immutable Obj two = new immutable Obj(...);
}

I get a compiler error in the two assignments to the static Obj 
member variables:
'this' is only defined in non-static member functions, not 
MyInfos


Is it related to the fact that the Obj class is encapsulated ?


Yes, nested classes have an implicit reference to their parent 
object, which doesn't exist in your case.





My goal is to be able to write things like this:

void main() {
   Info x1 = MyInfos.one, x2 = MyInfo.two, x3;
   assert(x3 is null);
   x3 = x1;
   assert(x3 is x1);
   assert(x3 is MyInfo.one);

   // Use static immutable instance references as case arg in 
switch

   switch(x1) {
   case MyInfo.one: ...;
   }
}


It looks like your don't actually need `Obj` to be a real nested 
class. Try declaring it as `static Obj : Info { }`. This should 
work if `Obj`'s methods don't need access to `MyInfo`'s 
non-static members.


Re: Immutable objects and constructor ?

2016-05-20 Thread chmike via Digitalmars-d-learn
The error message is gone, but I now have another compilation 
error message I don't understand.


This is what I have in fact

interface Info { . . . }

class MyInfos {
   . . .
protected:
   class Obj : Info
   {
   . . .
   }

public:
   static immutable Obj one = new immutable Obj(...);
   static immutable Obj two = new immutable Obj(...);
}

I get a compiler error in the two assignments to the static Obj 
member variables:

'this' is only defined in non-static member functions, not MyInfos

Is it related to the fact that the Obj class is encapsulated ?


My goal is to be able to write things like this:

void main() {
   Info x1 = MyInfos.one, x2 = MyInfo.two, x3;
   assert(x3 is null);
   x3 = x1;
   assert(x3 is x1);
   assert(x3 is MyInfo.one);

   // Use static immutable instance references as case arg in 
switch

   switch(x1) {
   case MyInfo.one: ...;
   }
}





Re: Immutable objects and constructor ?

2016-05-20 Thread chmike via Digitalmars-d-learn

On Friday, 20 May 2016 at 14:40:23 UTC, Kagamin wrote:

On Friday, 20 May 2016 at 14:06:54 UTC, chmike wrote:
But when I try to instantiate the class I get an dramatic 
compilation error:


"none of the overloads of '__ctor' are callable using a 
mutable object, candidates are: "


auto a=new immutable Info(1,"1");

How should I do if I would like to use the lazy pattern for 
initializing some member variables of the instance ?


Use mutable class.


Thank you very much for the fast and very helpful reply. I'll try 
that.







Re: Immutable objects and constructor ?

2016-05-20 Thread Kagamin via Digitalmars-d-learn

On Friday, 20 May 2016 at 14:06:54 UTC, chmike wrote:
But when I try to instantiate the class I get an dramatic 
compilation error:


"none of the overloads of '__ctor' are callable using a mutable 
object, candidates are: "


auto a=new immutable Info(1,"1");

How should I do if I would like to use the lazy pattern for 
initializing some member variables of the instance ?


Use mutable class.


Immutable objects and constructor ?

2016-05-20 Thread chmike via Digitalmars-d-learn


I'm implementing the flyweight pattern. It means that I have a 
set of object instances representing all the possible values. 
This allows me to manipulate "values" by simply manipulating 
references to the instance. Testing "value" equality boils down 
to simply compare reference value. I hope I can use these 
immutable instances as case argument of a switch, but I'm not 
there yet.


I have declared an immutable class.


immutable interface SomeInfo { ... }

immutable class Info : SomeInfo {
   @disable this();
   this(int codeValue, string codeName)
   {
   codeValue_ = (codeValue * 10) - 113; // some random 
example computation

   codeName_ = "Info."~codeName_;
   }
   private:
  int codeValue_;
  string codeName_;
}


But when I try to instantiate the class I get an dramatic 
compilation error:


"none of the overloads of '__ctor' are callable using a mutable 
object, candidates are: "


Adding immutable to the constructor doesn't help. How can I 
initialize the immutable instances of a class ?



I have seen it is possible to cast away the immutability. Does it 
also work for immutable classes ? Could I use an object factory ?


How should I do if I would like to use the lazy pattern for 
initializing some member variables of the instance ? Something 
like :


immutable class Info : SomeInfo
{
   ...
   string toString()
   {
  if (!toString_)
  synchronize { // make it thread safe
 if (!toString_)
toString_ = format("bla bla %s (%d)", codeName_, 
codeValue_);

  }
  return toString_;
   }
   ...
   private:
  string toString_;
}