[lug] Perl question

Tom Christiansen tchrist at perl.com
Mon Apr 6 19:50:43 MDT 2009


In-Reply-To: Message from Zan Lynx <zlynx at acm.org> 
   of "Mon, 06 Apr 2009 18:04:17 MDT." <49DA9881.1060501 at acm.org> 

> Any "use" statements must be inside the scope of the "package" that 
> wants to use them.  What is probably happening is something like this:

That's not really accurate.  If the "use" on a regular module triggers an
import, then yes, those exports will (likely) go into the namespace of
the caller's compile-time package.  However, there are also "use"
statements that have no affect on the package, but rather on the caller's
enclosing lexical scope, something that's orthogonal (=utterly unrelated)
to its package.  Witness:

    % perl -le 'use bignum; print 123->is_odd; package Other; print 245->is_odd'
    1
    1

The Switch.pm module is yet a different sort of beast altogether, and 
pretty nasty about it, too.  Have you *looked* at its import() method?

For one thing, it uses source filters, making it subject to strange
unreliabilities.  For example, try putting a colon on your case and see
what happens. There are other problems, too, because it shoves the callers
compilation unit (the current file)'s source code to be run through a
source filter, and it doesn't give a rat's patute what package you're in,
somewhat the way use strict or use bignum don't care.  Use the source.

As of perl 5.10.0, it's been replaced by a proper built-in control-flow
construct, enabled via 'use feature "switch"' or in any of several other
ways, including simply asking that you be running perl 5.010 or better.

We're trying to figure out how to shoot Switch.pm in the head, so you
should use the new switch not the old Switch.

Here's code for the old one, showing that it doesn't care about what
package's symbol table is currently being used for compiling (storing)
any global symbols into [nor does the new, of course]:

    #!/usr/bin/perl -l
    package main;
    use strict;
    use warnings;

    use Switch;

    sub foo {
        my $arg = shift();
        switch ($arg) {
            case 1      { print "foo one" }
            case 2      { print "foo two" }
            else        { print "foo not" }
        } 
    } 

    package niam;

    sub bar {
        my $arg = shift();
        switch ($arg) {
            case 1      { print "bar one" }
            case 2      { print "bar two" }
            else        { print "bar not" }
        } 
    } 

    package Home_Again;

    main::foo(1);
    niam::bar(2);
    main::foo(3);

    exit(0);

When run, that says:

    foo one
    bar two
    foo not

And here's the equivalent using the new, built-in construct:

    #!/usr/bin/perl 
    use 5.10.0;
    package main;
    use strict;
    use warnings;

    sub foo {
	my $arg = shift();
	given ($arg) {
	    when (1)        { say "foo one" }
	    when (2)        { say "foo two" }
	    default         { say "foo not" }
	} 
    } 

    package niam;

    sub bar {
	my $arg = shift();
	given ($arg) {
	    when (1)        { say "bar one" }
	    when (2)        { say "bar two" }
	    default         { say "bar not" }
	} 
    } 

    package Home_Again;

    main::foo(1);
    niam::bar(2);
    main::foo(3);

    exit(0);

The second version produces output identical to the first's.

--tom

    PS:  I feel I've been baited. :-)



More information about the LUG mailing list