Thread overview
immutable singleton pattern with static opCall
Jun 27, 2010
Justin Johansson
Jun 27, 2010
Michal Minich
Jun 27, 2010
Justin Johansson
Jun 28, 2010
Justin Johansson
Jun 28, 2010
Justin Johansson
Jun 28, 2010
Justin Johansson
Jun 28, 2010
Justin Johansson
June 27, 2010
The following declaration implements the classic singleton
design pattern and uses D's static opCall feature to make
for brevity of use, that is to say, you can access the singleton
instance by simply writing Foo() rather than Foo.instance.

Furthermore, the use of private on the static instance forces
use of the function call style idiom, i.e. Foo(), rather than
the long hand form Foo.instance.

class Foo
{
   static private Foo instance;

   static this() {
      instance = new Foo;
   }

   static Foo opCall() {
      return instance;
   }
}


Now I would like to make this class immutable.  How many times
should I have to type the immutable keyword to achieve this result?

Ideally once only would be my answer.  But the following, possibly naive
code, does not compile:

immutable class Foo
{
   static private Foo instance;

   static this() {			// line 9
      instance = new Foo;
   }

   static Foo opCall() {		// line 13
      return instance;
   }
}

test.d(9): Error: function test.Foo._staticCtor2 without 'this' cannot be const/immutable
test.d(13): Error: function test.Foo.opCall without 'this' cannot be const/immutable

How should this declaration best be written to achieve my design?  One
variation I have is as follows but it is very noisy with the immutable
keyword.

class Foo
{
   static private immutable Foo instance;

   static this() {
      instance = cast(immutable Foo) new Foo;
   }

   static immutable(Foo) opCall() {
      return instance;
   }
}


June 27, 2010
On Sun, 27 Jun 2010 09:36:04 +0930, Justin Johansson wrote:

> immutable class Foo
> {
>     static private Foo instance;
> 
>     static this() {			// line 9
>        instance = new Foo;
>     }
> 
>     static Foo opCall() {		// line 13
>        return instance;
>     }
> }
> 
> test.d(9): Error: function test.Foo._staticCtor2 without 'this' cannot
> be const/immutable
> test.d(13): Error: function test.Foo.opCall without 'this' cannot be
> const/immutable

there is bug report on this subject

http://d.puremagic.com/issues/show_bug.cgi?id=3598

Your example also uses static variable, which was not considered in the bug report. This makes things more complex to design properly, because it seems now that one does not want static functions to be affected by immutable attribute of class, but it should affect static data...
June 27, 2010
Michal Minich wrote:
> On Sun, 27 Jun 2010 09:36:04 +0930, Justin Johansson wrote:
> 
>> immutable class Foo
>> {
>>     static private Foo instance;
>>
>>     static this() {			// line 9
>>        instance = new Foo;
>>     }
>>
>>     static Foo opCall() {		// line 13
>>        return instance;
>>     }
>> }
>>
>> test.d(9): Error: function test.Foo._staticCtor2 without 'this' cannot
>> be const/immutable
>> test.d(13): Error: function test.Foo.opCall without 'this' cannot be
>> const/immutable
> 
> there is bug report on this subject
> 
> http://d.puremagic.com/issues/show_bug.cgi?id=3598
> 
> Your example also uses static variable, which was not considered in the bug report. This makes things more complex to design properly, because it seems now that one does not want static functions to be affected by  immutable attribute of class, but it should affect static data...

Thanks for your quick response and analysis.

I agree that "it should affect static data".  Since this bug impedes
the use of good functional style, imho this is a *serious* bug.
June 28, 2010
On Sat, 26 Jun 2010 20:19:44 -0400, Michal Minich <michal.minich@gmail.com> wrote:

> On Sun, 27 Jun 2010 09:36:04 +0930, Justin Johansson wrote:
>
>> immutable class Foo
>> {
>>     static private Foo instance;
>>
>>     static this() {			// line 9
>>        instance = new Foo;
>>     }
>>
>>     static Foo opCall() {		// line 13
>>        return instance;
>>     }
>> }
>>
>> test.d(9): Error: function test.Foo._staticCtor2 without 'this' cannot
>> be const/immutable
>> test.d(13): Error: function test.Foo.opCall without 'this' cannot be
>> const/immutable
>
> there is bug report on this subject
>
> http://d.puremagic.com/issues/show_bug.cgi?id=3598
>
> Your example also uses static variable, which was not considered in the
> bug report. This makes things more complex to design properly, because it
> seems now that one does not want static functions to be affected by
> immutable attribute of class, but it should affect static data...

static variables inside an immutable class should be immutable.  That was considered in the bug report and purposefully left out.

The issue is that the compiler incorrectly labels static *functions* as immutable which makes no sense, static functions cannot be immutable ever.  Static data can be.

BTW, you can work around this problem like this:

class Foo
{
   static immutable instance; // no need to make private, it can never change

   static this() {
      instance = new Foo;  // not sure if this works, you may have to cast.
   }

   static immutable(Foo) opCall() {
      return instance;
   }

   immutable:

   // member functions
}

-Steve
June 28, 2010
Steven Schveighoffer wrote:
> On Sat, 26 Jun 2010 20:19:44 -0400, Michal Minich <michal.minich@gmail.com> wrote:
> 
>> On Sun, 27 Jun 2010 09:36:04 +0930, Justin Johansson wrote:
>>
>>> immutable class Foo
>>> {
>>>     static private Foo instance;
>>>
>>>     static this() {            // line 9
>>>        instance = new Foo;
>>>     }
>>>
>>>     static Foo opCall() {        // line 13
>>>        return instance;
>>>     }
>>> }
>>>
>>> test.d(9): Error: function test.Foo._staticCtor2 without 'this' cannot
>>> be const/immutable
>>> test.d(13): Error: function test.Foo.opCall without 'this' cannot be
>>> const/immutable
>>
>> there is bug report on this subject
>>
>> http://d.puremagic.com/issues/show_bug.cgi?id=3598
>>
>> Your example also uses static variable, which was not considered in the
>> bug report. This makes things more complex to design properly, because it
>> seems now that one does not want static functions to be affected by
>> immutable attribute of class, but it should affect static data...
> 
> static variables inside an immutable class should be immutable.  That was considered in the bug report and purposefully left out.
> 
> The issue is that the compiler incorrectly labels static *functions* as immutable which makes no sense, static functions cannot be immutable ever.  Static data can be.
> 
> BTW, you can work around this problem like this:
> 
> class Foo
> {
>    static immutable instance; // no need to make private, it can never change
> 
>    static this() {
>       instance = new Foo;  // not sure if this works, you may have to cast.
>    }
> 
>    static immutable(Foo) opCall() {
>       return instance;
>    }
> 
>    immutable:
> 
>    // member functions
> }
> 
> -Steve

Thanks Steve.

btw. The reason I marked the static instance member as private
was simply to enforce stylist use of Foo() rather than Foo.instance

You guess is correct; I found that you have to use a cast with
instance = new Foo
but then I discovered that you can avoid the cast by writing
a trivial constructor marked with immutable, i.e.
immutable this {}
Though this doesn't reduce the headcount of the uses of the immutable
keyword, I think it looks nicer than a cast.  Your idea of immutable:
though is good for the remainder of the member functions (and the
trivial ctor).

My immutable singleton pattern now looks like this :-)


class Foo
{
   // following marked private for stylistic enforcement
   static immutable private Foo instance;

   static this() {
      // following works without cast thanks to immutable ctor
      instance = new Foo;
   }

   static immutable(Foo) opCall() {
     return instance;
   }

immutable:
  this() {}

  // more immutable member function decls following
  // ..
}


Cheers
Justin
June 28, 2010
On Mon, 28 Jun 2010 08:07:40 -0400, Justin Johansson <no@spam.com> wrote:

> Steven Schveighoffer wrote:
>> On Sat, 26 Jun 2010 20:19:44 -0400, Michal Minich <michal.minich@gmail.com> wrote:
>>
>>> On Sun, 27 Jun 2010 09:36:04 +0930, Justin Johansson wrote:
>>>
>>>> immutable class Foo
>>>> {
>>>>     static private Foo instance;
>>>>
>>>>     static this() {            // line 9
>>>>        instance = new Foo;
>>>>     }
>>>>
>>>>     static Foo opCall() {        // line 13
>>>>        return instance;
>>>>     }
>>>> }
>>>>
>>>> test.d(9): Error: function test.Foo._staticCtor2 without 'this' cannot
>>>> be const/immutable
>>>> test.d(13): Error: function test.Foo.opCall without 'this' cannot be
>>>> const/immutable
>>>
>>> there is bug report on this subject
>>>
>>> http://d.puremagic.com/issues/show_bug.cgi?id=3598
>>>
>>> Your example also uses static variable, which was not considered in the
>>> bug report. This makes things more complex to design properly, because it
>>> seems now that one does not want static functions to be affected by
>>> immutable attribute of class, but it should affect static data...
>>  static variables inside an immutable class should be immutable.  That was considered in the bug report and purposefully left out.
>>  The issue is that the compiler incorrectly labels static *functions* as immutable which makes no sense, static functions cannot be immutable ever.  Static data can be.
>>  BTW, you can work around this problem like this:
>>  class Foo
>> {
>>    static immutable instance; // no need to make private, it can never change
>>     static this() {
>>       instance = new Foo;  // not sure if this works, you may have to cast.
>>    }
>>     static immutable(Foo) opCall() {
>>       return instance;
>>    }
>>     immutable:
>>     // member functions
>> }
>>  -Steve
>
> Thanks Steve.
>
> btw. The reason I marked the static instance member as private
> was simply to enforce stylist use of Foo() rather than Foo.instance

Yuck Foo().xyz :)

But, whatever floats your boat.

>
> You guess is correct; I found that you have to use a cast with
> instance = new Foo
> but then I discovered that you can avoid the cast by writing
> a trivial constructor marked with immutable, i.e.
> immutable this {}

Ah, that is good.  However, I was also unsure if a static immutable could be set inside a static constructor.  That is also good, immutable has definitely gotten a lot easier to use!

> Though this doesn't reduce the headcount of the uses of the immutable
> keyword, I think it looks nicer than a cast.  Your idea of immutable:
> though is good for the remainder of the member functions (and the
> trivial ctor).

I have a feeling that the afore mentioned bug will eventually be fixed, and at that point, you can just make Foo an immutable class with no issues.

>
> My immutable singleton pattern now looks like this :-)
>
>
> class Foo
> {
>     // following marked private for stylistic enforcement
>     static immutable private Foo instance;
>
>     static this() {
>        // following works without cast thanks to immutable ctor
>        instance = new Foo;
>     }
>
>     static immutable(Foo) opCall() {
>       return instance;
>     }
>
> immutable:
>    this() {}
>
>    // more immutable member function decls following
>    // ..
> }

To go one step further, if you want it to truly be a singleton type, you should mark the constructor private.

-Steve
June 28, 2010
Steven Schveighoffer wrote:
> On Mon, 28 Jun 2010 08:07:40 -0400, Justin Johansson <no@spam.com> wrote:
> 
>> Steven Schveighoffer wrote:
>>
>> btw. The reason I marked the static instance member as private
>> was simply to enforce stylist use of Foo() rather than Foo.instance
> 
> Yuck Foo().xyz :)
> 
> But, whatever floats your boat.

He he, that's a cute quip.

> To go one step further, if you want it to truly be a singleton type, you should mark the constructor private.
> 
> -Steve

Indeed.  I forgot the private constructor in this version but had it
in earlier versions.

Continuing on with the saga, it's a pity that immutable
is not compatible with Object toString method without a cast.

class Foo
{
   static immutable private Foo instance;

   static this() {
      instance = new Foo;
   }

   static immutable(Foo) opCall() {
     return instance;
   }

immutable:
  private this() {}
}


void main()
{
   // numerous compile errors if the cast is left out
   stdout.writefln( "Foo() = %s", cast(Foo) Foo());
}

JJ
June 28, 2010
On Mon, 28 Jun 2010 08:40:36 -0400, Justin Johansson <no@spam.com> wrote:

> Steven Schveighoffer wrote:
>> On Mon, 28 Jun 2010 08:07:40 -0400, Justin Johansson <no@spam.com> wrote:
>>
>>> Steven Schveighoffer wrote:
>> To go one step further, if you want it to truly be a singleton type, you should mark the constructor private.
>>  -Steve
>
> Indeed.  I forgot the private constructor in this version but had it
> in earlier versions.
>
> Continuing on with the saga, it's a pity that immutable
> is not compatible with Object toString method without a cast.
>
> class Foo
> {
>     static immutable private Foo instance;
>
>     static this() {
>        instance = new Foo;
>     }
>
>     static immutable(Foo) opCall() {
>       return instance;
>     }
>
> immutable:
>    private this() {}
> }
>
>
> void main()
> {
>     // numerous compile errors if the cast is left out
>     stdout.writefln( "Foo() = %s", cast(Foo) Foo());
> }

That's because toString should be a const function.

See http://d.puremagic.com/issues/show_bug.cgi?id=1824

please vote for the bug.

-Steve
June 28, 2010
Steven Schveighoffer wrote:
> On Mon, 28 Jun 2010 08:40:36 -0400, Justin Johansson <no@spam.com> wrote:
> 
>> Steven Schveighoffer wrote:
>>> On Mon, 28 Jun 2010 08:07:40 -0400, Justin Johansson <no@spam.com> wrote:
>>>
>>>> Steven Schveighoffer wrote:
>>> To go one step further, if you want it to truly be a singleton type, you should mark the constructor private.
>>>  -Steve
>>
>> Indeed.  I forgot the private constructor in this version but had it
>> in earlier versions.
>>
>> Continuing on with the saga, it's a pity that immutable
>> is not compatible with Object toString method without a cast.
>>
>> class Foo
>> {
>>     static immutable private Foo instance;
>>
>>     static this() {
>>        instance = new Foo;
>>     }
>>
>>     static immutable(Foo) opCall() {
>>       return instance;
>>     }
>>
>> immutable:
>>    private this() {}
>> }
>>
>>
>> void main()
>> {
>>     // numerous compile errors if the cast is left out
>>     stdout.writefln( "Foo() = %s", cast(Foo) Foo());
>> }
> 
> That's because toString should be a const function.
> 
> See http://d.puremagic.com/issues/show_bug.cgi?id=1824
> 
> please vote for the bug.
> 
> -Steve

That's a pretty fundamental oversight.

just signed up new account (procode == me) and voted for the bug

JJ
June 28, 2010
Steven Schveighoffer wrote:
> On Mon, 28 Jun 2010 08:07:40 -0400, Justin Johansson <no@spam.com> wrote:
> 
>> Steven Schveighoffer wrote:
>>> On Sat, 26 Jun 2010 20:19:44 -0400, Michal Minich <michal.minich@gmail.com> wrote:
>>>
>>>> On Sun, 27 Jun 2010 09:36:04 +0930, Justin Johansson wrote:
>>>>
>>>>> immutable class Foo
>>>>> {
>>>>>     static private Foo instance;
>>>>>
>>>>>     static this() {            // line 9
>>>>>        instance = new Foo;
>>>>>     }
>>>>>
>>>>>     static Foo opCall() {        // line 13
>>>>>        return instance;
>>>>>     }
>>>>> }
>>>>>
>>>>> test.d(9): Error: function test.Foo._staticCtor2 without 'this' cannot
>>>>> be const/immutable
>>>>> test.d(13): Error: function test.Foo.opCall without 'this' cannot be
>>>>> const/immutable
>>>>
>>>> there is bug report on this subject
>>>>
>>>> http://d.puremagic.com/issues/show_bug.cgi?id=3598
>>>>
>>>> Your example also uses static variable, which was not considered in the
>>>> bug report. This makes things more complex to design properly, because it
>>>> seems now that one does not want static functions to be affected by
>>>> immutable attribute of class, but it should affect static data...
>>>  static variables inside an immutable class should be immutable.  That was considered in the bug report and purposefully left out.
>>>  The issue is that the compiler incorrectly labels static *functions* as immutable which makes no sense, static functions cannot be immutable ever.  Static data can be.
>>>  BTW, you can work around this problem like this:
>>>  class Foo
>>> {
>>>    static immutable instance; // no need to make private, it can never change
>>>     static this() {
>>>       instance = new Foo;  // not sure if this works, you may have to cast.
>>>    }
>>>     static immutable(Foo) opCall() {
>>>       return instance;
>>>    }
>>>     immutable:
>>>     // member functions
>>> }
>>>  -Steve
>>
>> Thanks Steve.
>>
>> btw. The reason I marked the static instance member as private
>> was simply to enforce stylist use of Foo() rather than Foo.instance
> 
> Yuck Foo().xyz :)
> 
> But, whatever floats your boat.

I should explain the method to my madness.

Initially I was doing something else with static opCall and immutability
and then ran into the problem covered in this thread.  To save writing a
long story on this ng I reduced the problem to something that could be easily understood by choosing to demonstrate it via the singleton
pattern.

My actual use case is not a singleton pattern at all.  Rather my static
opCall for the immutable class(es) in question will normally take one
or more arguments.  The arguments will be validated first by the static
opCall.  Only then if the arguments are valid will a constructor be
called for some appropriate concrete subclass of the (abstract) class
in which the static opCall is declared.  This technique is
reminiscent of a factory pattern though I'll be using it to effect
a mechanism for memoizing results.  The overall agenda, being truly
idiomatic of functional programming, is to create a new instance of
some class only if there has not already been an invocation of the
static opCall with the same arguments.

Cheers and thanks again to Steve & Michal for all help.
Justin