Perl Singleton

By convention, a Perl5 class's constructor is typically written to create a new object by blessing a new anonymous hash (or other reference). (Smalltalkers will note the similarity between bless and a one-way #become:) Objects created in this manner are distinct.

Arranging to create and return a singleton object is straightforward: bless an object when the constructor (e.g. new) is first invoked, remember that object, and hand it out on subsequent invocations of the constructor.

[Singleton.pm] package Singleton;

my $singleton;

sub new { my $class = shift; $singleton ||= bless {}, $class; }

...

[foo.pl] require Singleton;

my $object1 = new Singleton; my $object2 = new Singleton; # same object!


Yet another way (I won't claim this is better, but it avoids any extra logic on subsequent calls to new):

package Foo;

sub new { *new = \&old; $Foo::bar = bless {}, shift; }

sub old { $Foo::bar; }


An alternative is to exploit the feature that perl classes are just namespaces (i.e. packages) with functions in them. Since every namespace is automatically unique in a perl program, it can be a singleton object itself. In this case, the "object" is the name of the class.

Like so:

my $sngl = 'Some::Singleton::Class';

$sngl->foo;

as long as that subroutine exists in that package, everything works fine.

There are, of course, ways to wrap this approach in an abstraction that makes it look like normal (blessed-ref) object usage.

------------

[Perl punctuation commentary follows]

The ||= operator is a handy lazy assignment operator which evaluates the rhs and assigns it to the lhs if and only if the lhs evaluates as false.

(The only "problem" is that || tests for truth, not definedness. However, references are always true, so there is no problem in this case.)

So equivalent long-hand notations include:

$singleton = bless {}, $class unless $singleton; $singleton or $singleton = bless {}, $class; $singleton = $singleton ? $singleton : bless {}, $class;

Using these longer forms, you can test for definedness explicitly.

As always, There Is More Than One Way To Do It... but consider that

||= gives the lowest Perl Golf score ;-).

And since perl 5.9.0, you can use //= to test the definedness.


I do something like this now: 1. Class Name::Class Singleton() for access to a single instance of the class. 2. Class Name::Singleton(primary key) to get a cached version or create an object and then cache it.

I find these idioms easy and obvious. Being too clever isn't a win.


I find that "new" is inappropriate in a singleton API. My view is that you should not call a constructor, but instead a getInstance () method. That way, it's lucid in your client code that indeed you're dealing with a singleton. It will help you avoid hours of searching when you're wondering why several "new" objects are not really new at all.

hubo


See original on c2.com