[Catalyst] Re: using Plugin::Singleton and testing

A. Pagaltzis pagaltzis at gmx.de
Mon Nov 20 18:20:56 GMT 2006


* Daniel McBrearty <danielmcbrearty at gmail.com> [2006-11-20 16:25]:
> >>>> A global is something that is in the global namespace.
> >>>> A singleton isn't, any more than other class is. You have
> >>>> to import the class to which it belongs to use it.
> >>>
> >>> That might be true in Java. It's patently false in Perl.
> >>
> >> (file MySingleton.pm)
> >> package MySingleton;
> >>
> >> ...
> >>
> >> sub get_instance {
> >> # the standard stuff ...
> >> }
> >>
> >> 1;
> >>
> >>
> >> (EOF)
> >>
> >> please explain how it is possible to get hold of this object
> >> without doing
> >>
> >> use MySingleton;
> >>
> >> my $s = MySinglton->get_instance;
> >>
> >> (assuming that you don't deliberately export into the global
> >> namespace, which can be the case with any class)
> >
> >If you do `use MySingleton` in any part of the code, it's
> >possible to say `MySingleton->get_instance` in any other part.
> >In Java, this is not so.
> 
> That's true. But - BIG but - it's STILL not in the global
> namespace.

You can refer to the MySingleton package from any other part of
the code, whether it has explicitly asked for it or not. If
that’s not global, I don’t know what is.

Sure, it doesn’t come from the package variable namespace, it
comes from the packagename namespace… but a global is a global is
a global is a global.

> If you do as you advoctae - a true global ... )
> 
> our $my_singleton = ....
> 
> in your main file, $my_singleton anywhere clashes with that.

No, it does not. Any time you write $::my_singleton or
$main::my_singleton, it refers exactly to the scalar in the glob
called `my_singleton` in the `main` package. Package variables
and lexicals live in two different namespaces, although for
typical you can conflate them as a convenience. (Amusingly, it’s
possible to specifically ask for package variables regardless of
any same-named lexical variables, but it’s not possible to ask
for lexical variables without a fallback to same-named package
variables defined in the current package.)

=begin sidenote

Btw, `our` only works as you seem to expect within a single
package. There are two completely different variables $bar in
the following example:

    package foo;
    our $bar;
    package baz;
    our $bar;

But you can unambiguously refer to either of them with $foo::bar
and $baz::bar.

What `our` does is declare the name of package variable for
a single lexical scope:

    use strict;

    sub foo {
        our $bar;   # strict.pm knows about $main::bar
    }

    $bar = 1; # strict.pm complains; $main::bar is undeclared here!

    sub bar {
        our $bar;   # same $main::bar as in foo()
    }

Confusing? And it doesn’t save you from typos:

    use strict;

    sub foo {
        our $bar;   # as always...
    }

    sub bar {
        our $baf;   # oops! wrong declaration, but strict.pm can't know that
    }

Bottom line, I still use `use vars`…

=end sidenote

> What's more if you encounter it in some other file you will
> need to grep for it.
>
> MySingelton->get_instance;
> 
> (or, if you prefer $MySingleton::instance         .... )
> 
> does not suffer from that problem.

I don’t see how you would find instances of this in other files
in any other way that by grepping?

The arguments you bring up seem to rely on the fact that class
names come from the package namespace, which tends to have many
fewer entries than the *overall* variable namespace, so global
names coming from the package namespace seem to stand out more
and be easier to find. In practice, I doubt this intuition will
hold; I’m pretty certain that most moderately sized, decently
written Perl apps have more classes than they have scalars in any
single package.

Regards,
-- 
Aristotle Pagaltzis // <http://plasmasturm.org/>



More information about the Catalyst mailing list