December 17, 2011
On 12/17/11 6:34 AM, so wrote:
> If you are using singleton in your C++/D (or any other M-P language)
> code, do yourself a favor and trash that book you learned it from.
>
> ---
> class A {
> static A make();
> }
>
> class B;
> B makeB();
> ---
>
> What A.make can do makeB can not? (Other than creating objects of two
> different types :P )

Singleton has two benefits. One, you can't accidentally create more than one instance. The second, which is often overlooked, is that you still benefit of polymorphism (as opposed to making its state global).

Andrei
December 17, 2011
On Sat, 17 Dec 2011 21:20:33 +0200, Andrei Alexandrescu
<SeeWebsiteForEmail@erdani.org> wrote:

> On 12/17/11 6:34 AM, so wrote:
>> If you are using singleton in your C++/D (or any other M-P language)
>> code, do yourself a favor and trash that book you learned it from.
>>
>> ---
>> class A {
>> static A make();
>> }
>>
>> class B;
>> B makeB();
>> ---
>>
>> What A.make can do makeB can not? (Other than creating objects of two
>> different types :P )
>
> Singleton has two benefits. One, you can't accidentally create more than one instance. The second, which is often overlooked, is that you still benefit of polymorphism (as opposed to making its state global).
>
> Andrei

Now i am puzzled,
"makeB" does both and does better. (better as it doesn't expose any detail to user)
December 17, 2011
On Saturday, 17 December 2011 at 21:02:58 UTC, so wrote:
> On Sat, 17 Dec 2011 21:20:33 +0200, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org> wrote:
>
>> On 12/17/11 6:34 AM, so wrote:
>>> If you are using singleton in your C++/D (or any other M-P language)
>>> code, do yourself a favor and trash that book you learned it from.
>>>
>>> ---
>>> class A {
>>> static A make();
>>> }
>>>
>>> class B;
>>> B makeB();
>>> ---
>>>
>>> What A.make can do makeB can not? (Other than creating objects of two
>>> different types :P )
>>
>> Singleton has two benefits. One, you can't accidentally create more than one instance. The second, which is often overlooked, is that you still benefit of polymorphism (as opposed to making its state global).
>>
>> Andrei
>
> Now i am puzzled,
> "makeB" does both and does better. (better as it doesn't expose any detail to user)

Both of your examples are the singleton pattern if `make` returns the same instance every time, and arguably (optionally?) A or B shouldn't be instantiable in any other way.

I suspect that the reason a static member function is prevalent is because it's easy to just make the constructor private (and not have to mess with things like C++'s `friend`). In D, there's no real difference because you can still use private members as long as you're in the same module.

The only difference between them I can see is that the module-level function doesn't expose the class name directly when using the function, which is but a minor improvement.
December 18, 2011
On Saturday, December 17, 2011 19:44:28 deadalnix wrote:
> Very good point. CTFE is improving with each version of dmd, and is a real alternative to static this(); It should be considered when apropriate, it has many benefices.

I think that in general, the uses for static this fall into one of two categories:

1. Initializing stuff that can't be initialized at compile time. This includes stuff like classes or AAs as well as stuff which needs to be initialized with a value which isn't known until runtime (e.g. when the program started running).

2. Calling functions which need to be called at the beginning of the program (e.g. a function which does something to the environment that the program is running in).

As CTFE improves, #1 should become smaller and smaller, and static this should be needed less and less, but #2 will always remain. It _is_ however the far rarer of the two use cases. So, ultimately static this may become very rare.

- Jonathan M Davis
December 18, 2011
On Saturday, December 17, 2011 13:20:33 Andrei Alexandrescu wrote:
> On 12/17/11 6:34 AM, so wrote:
> > If you are using singleton in your C++/D (or any other M-P language) code, do yourself a favor and trash that book you learned it from.
> > 
> > ---
> > class A {
> > static A make();
> > }
> > 
> > class B;
> > B makeB();
> > ---
> > 
> > What A.make can do makeB can not? (Other than creating objects of two
> > different types :P )
> 
> Singleton has two benefits. One, you can't accidentally create more than one instance. The second, which is often overlooked, is that you still benefit of polymorphism (as opposed to making its state global).

Yes. There are occasions when singleton is very useful and makes perfect sense. There's every possibity that it's a design pattern which is overused, and if you don't need it, you probably shouldn't use it, but there _are_ cases where it's useful.

In the case of std.datetime, the UTC and LocalTime classes are singletons because there's absolutely no point in ever allocating multiple of them. It would be a waste of memory. Imagine if

auto time = Clock.currTime();

had to allocate a LocalTime object every time. That's a lot of useless heap allocation. By making it a singleton, it's far more efficient. Currently, it does _no_ heap allocation, and once the singleton becomes lazy, it'll only allocate on the first call. I don't see a valid reason _not_ to use a singleton in this case - certainly not as long as time zones are classes, and I think that they make the most sense as classes considering what they have to do and how they have to behave.

- Jonathan M Davis
December 18, 2011
On Sat, 17 Dec 2011 23:12:16 +0200, Jakob Ovrum <jakobovrum@gmail.com> wrote:

> I suspect that the reason a static member function is prevalent is because it's easy to just make the constructor private (and not have to mess with things like C++'s `friend`). In D, there's no real difference because you can still use private members as long as you're in the same module.

Exactly. there is no difference between "static A.make" and "makeA" in D.

> The only difference between them I can see is that the module-level function doesn't expose the class name directly when using the function, which is but a minor improvement.

You have to expose either way no? "A.make" instead of "makeA"
December 18, 2011
On Sunday, 18 December 2011 at 08:56:56 UTC, so wrote:
> You have to expose either way no? "A.make" instead of "makeA"

Yeah, in most sane code, I would imagine so. But still, the original example was just `make` version `A.make`. They could both obscure their return type through various means (like auto), but imo it makes less sense to do so for the static member function - I would be surprised to call `A.make` and not get a value of type `A`. But it would only be a tiny improvement and I don't think it's really relevant to the singleton pattern.
December 18, 2011
On Sunday, 18 December 2011 at 09:26:58 UTC, Jakob Ovrum wrote:
> On Sunday, 18 December 2011 at 08:56:56 UTC, so wrote:
>> You have to expose either way no? "A.make" instead of "makeA"
>
> Yeah, in most sane code, I would imagine so. But still, the original example was just `make` version `A.make`. They could both obscure their return type through various means (like auto), but imo it makes less sense to do so for the static member function - I would be surprised to call `A.make` and not get a value of type `A`. But it would only be a tiny improvement and I don't think it's really relevant to the singleton pattern.

Sorry, I'm wrong, that wasn't the case at all. The original example was indeed `A.make` versus `makeB`.
December 18, 2011
Le 18/12/2011 03:01, Jonathan M Davis a écrit :
> On Saturday, December 17, 2011 19:44:28 deadalnix wrote:
>> Very good point. CTFE is improving with each version of dmd, and is a real alternative to static this(); It should be considered when apropriate, it has many benefices.
> 
> I think that in general, the uses for static this fall into one of two categories:
> 
> 1. Initializing stuff that can't be initialized at compile time. This includes stuff like classes or AAs as well as stuff which needs to be initialized with a value which isn't known until runtime (e.g. when the program started running).
> 
> 2. Calling functions which need to be called at the beginning of the program (e.g. a function which does something to the environment that the program is running in).
> 
> As CTFE improves, #1 should become smaller and smaller, and static this should be needed less and less, but #2 will always remain. It _is_ however the far rarer of the two use cases. So, ultimately static this may become very rare.
> 
> - Jonathan M Davis

In the Java/C# world, they use dependency injection frameworks like Google Guice or picocontainer to deal with this issue. In the case of datetime, though, I suspect it would be a using a hammer to crush a fly.
December 18, 2011
Am 16.12.2011, 23:08 Uhr, schrieb Steven Schveighoffer <schveiguy@yahoo.com>:

> Note that on Linux today, the executable is not truly static -- OS libs are dynamically linked.

That should hold true for any OS. Otherwise, how would the program communicate with the kernel and drivers, i.e. render a button on the screen? Some dynamically linked in functions must provide the interface to that "administrative singleton" that manages system resources.
1 2 3 4 5 6 7 8 9 10 11 12
Top | Discussion index | About this forum | D home