6

I'm looking at some code, but I don't understand what the following line is doing/checking:

return if !%Foo::Details:: ;

What exactly is this doing? Is it checking for the existence of module Foo::Details?

Nosrettap
  • 10,940
  • 23
  • 85
  • 140
  • 3
    Looks like a really poor way of testing whether a module has been loaded into the symbol table. `%Foo::Details` is the symbol table entry for the package `Foo::Details`, if it isn't loaded it will return false, which when negated returns true. Take a look at [`the symbol table section of perlmod`](http://perldoc.perl.org/perlmod.html#Symbol-Tables) – Hunter McMillen Apr 14 '14 at 18:49
  • @HunterMcMillen I think it's elegant, solely based on its compactness. What exactly makes it poor? – Jarmund Apr 14 '14 at 18:51
  • 1
    It isn't very clear (at first) what this piece of code is doing, that is why I think it's *poor*. There are better, more readable, solutions. – Hunter McMillen Apr 14 '14 at 18:53
  • Why does it have two colons on the end (`Foo::Details::` rather than `Foo::Details`)? Is that just the syntax? – Nosrettap Apr 14 '14 at 18:54
  • @Nosrettap The first sentence of the page I linked answers that question. – Hunter McMillen Apr 14 '14 at 18:55
  • 1
    @HunterMcMillen Thanks! If you put your comment in an answer I'll accept it. – Nosrettap Apr 14 '14 at 18:58
  • Re "`%Foo::Details` is the symbol table entry for the package", That should be `%Foo::Details::`. – ikegami Apr 14 '14 at 19:03
  • @ikegami yes, I realized I left it off a few minutes ago, but am outside of the edit comment window :| – Hunter McMillen Apr 14 '14 at 19:03
  • @HunterMcMillen alright, I was just curious if it was horribly inefficient or something like that. – Jarmund Apr 14 '14 at 19:07
  • 1
    @Jarmund, a reason it's a poor way of checking whether a module is loaded is that `%Foo::Bar::` will evaluate to true if module "Foo::Bar::Baz" is loaded **even if "Foo::Bar" is not loaded!** – tobyink Apr 14 '14 at 22:14

2 Answers2

9

A hash in scalar context returns false if it's empty, so your code returns an empty list if the hash %Foo::Details:: is empty.

That hash is the symbol table for the Foo::Details namespace. If a package variable or sub is created in the Foo::Details namespace, a glob corresponding to the name of the variable or sub will be created in %Foo::Details::. So, it returns an empty list if the Foo::Details namespace is empty.

$ cat >Foo/Details.pm
package Foo::Details;
sub boo { }
1;

$ perl -E'say %Foo::Details:: ?1:0;'
0

$ perl -E'use Foo::Details; say %Foo::Details:: ?1:0;'
1

It might be trying to check if the Foo::Details module has been loaded, but it's not perfect. For example, it will think Foo::Details has been loaded even if only Foo::Details::Bar has been loaded. To check if Foo::Details has been loaded, it might be better to check if $INC{"Foo/Details.pm"} is true. The problem with that approach is that it won't find "inlined modules".

ikegami
  • 367,544
  • 15
  • 269
  • 518
3

This code tests whether or not a module has been loaded. %Foo::Details:: is the symbol table for the module Foo::Details.

If Foo::Details was never loaded %Foo::Details:: will return false (because it contains no elements), which when negated with ! will return true and return from whatever function you are in.

You can read more about symbol tables in perlmod#Symbol Tables

Also, here is another SO post that talks about ways to determine if a module was loaded.

Community
  • 1
  • 1
Hunter McMillen
  • 59,865
  • 24
  • 119
  • 170
  • more correct to say %Foo::Details:: *is* the symbol table for the module – ysth Apr 14 '14 at 19:04
  • Isn't it technically an entry? Since it is held in `%main::`? – Hunter McMillen Apr 14 '14 at 19:05
  • Each element of %Foo::Details:: is an entry. %Foo::Details:: contains the entries for the Foo::Details namespace, which is to say it's the symbol table for Foo::Details. – ikegami Apr 14 '14 at 19:06
  • the symbol table *entry* for Foo::Details is `$Foo::{'Details::'}` (which is a glob that contains %Foo::Details:: in its hash slot). – ysth Apr 14 '14 at 19:22