5
$\begingroup$

Background

The singleton pattern is a widely used design pattern in the OOP language.

I'm considering adding a built-in singleton declaration to my language.

In Scala and Kotlin, we can use object to directly declare a singleton.

The advantage is that users can write less boilerplate code, and even thread bugs are hidden in the various template codes.

But my language is not strictly OOP, I also support global variables and lazy initialization, is it superfluous to use singleton mode at this time?

Question

Does the singleton pattern have advantages over global variables?

For what reasons do languages add built-in singleton keywords?

$\endgroup$

2 Answers 2

3
$\begingroup$

It depends (yes, I know... it always depends.)

The singleton pattern, when implemented manually in the code, allows one to customize how and when the initial creation takes place, and how multi-threading is handled (if it is).

On the other hand, providing singletons through a keyword gives to the user only one particular built-in implementation.

This might be good if you want that implementation to do something in particular, maybe in relation with some other features of your language.

Otherwise, it depends whether you expect that users may need to customize the provided implementation. This in turn depends on the design goals of your language.

Languages oriented towards high-performance or low-level tuning might want to let the user do exactly what's right for them.

Languages with a more high-level perspective or DSLs might want to relieve the user from having to think about it and provide them with a good and easy to use default.

$\endgroup$
2
$\begingroup$

Singletons can be lazily initialized

An object in Kotlin is always created when it is declared. It will consume RAM and time to construct regardless of if it is used. Tree shaking can maybe remove the declaration if it never used at all but not if it's called in some code branch and that branch is never reached.

Singletons on the other hand are lazy initialized. If they need some complex computation to construct or use a lot of memory or file handles or other rare resources, they won't use them till they are needed. This can be an advantage in certain situations.

Of course, the lazy behavior can be emulated with mutable globals without needing a specialized singleton keyword. You may consider most cases can be easily handled using object declarations that it's not worth creating an entire new syntax for something that would cost 2-5 lines of code to emulate.

It would also be quite easy to create a library to emulate a singleton feature based on simple object literals. You could consider simply adding such a function to the standard library instead of creating a specialized syntax for it. For example Rust the once_cell is scheduled to be added to the standard library soon.

$\endgroup$
3
  • $\begingroup$ Note that the singleton pattern takes more than 2 lines of code; 3 lines in Kotlin, 5 in Java (excluding braces and empty lines) $\endgroup$
    – Seggan
    Commented Jul 4, 2023 at 13:34
  • $\begingroup$ In languages that support ?? you can do static Self getInstance() {return Self::instance??=new Instance(..)} for 2 lines. If you don't have such an operator it would add more. $\endgroup$
    – mousetail
    Commented Jul 4, 2023 at 14:00
  • 1
    $\begingroup$ A general way to declare a variable initialization as lazy might not be that useless of a syntax feature in general. $\endgroup$
    – Philipp
    Commented Jul 4, 2023 at 14:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .