Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

How does strict determine if something is legally declared?

by dragonchild (Archbishop)
on Jan 10, 2006 at 03:25 UTC ( [id://522079]=perlquestion: print w/replies, xml ) Need Help??

dragonchild has asked for the wisdom of the Perl Monks concerning the following question:

I'm writing "Yet Another Perl OO Framework", primarily for fun. This is meant to be as close to my style (which is oddly very close to Ruby) for my own personal code. I doubt I will ever release this to CPAN - it's largely meant for me to play with some of the odds corners of Perl. And, I've hit one of them.

The class declaration code looks something like:

package Foo; #use strict; use Class; class { attr qw( foo bar ); isa 'Foo::Base'; method floozle => signature (Int, Int), body { my ($v1, $v2) = @_; $self->foo( $v1 ); return $self->get_bar( $v2 ); }; }; package main; my $obj = Foo->new; $foo->set_foo( 3 ); $foo->floozle( 9, 5 ); # These croak $foo->floozle() $foo->floozle( 9, 'a' );

The astute observer will notice that $self is never declared anywhere, yet this does work just fine ... so long as you're not under strict. And, I have no idea why.

Class::import() (called during use) creates $Class::self in the caller's namespace. I would think that the existence of this variable before the reference to $self is compiled in the body declaration would satisfy strict. But, it apparently doesn't. And, it's the oddest set of errors:

Variable "$self" is not imported at t/lib/Foo.pm line ##. Global symbol "$self" requires explicit package name at t/lib/Foo.pm l +ine ##.

"use diagnostics" doesn't help much:

Variable "%s" is not imported%s (F) While "use strict" in effect, you referred to a global variabl +e that you apparently thought was imported from another module, becau +se something else of the same name (usually a subroutine) is exported + by that module. It usually means you put the wrong funny character o +n the front of your variable.

So, my questions are:

  • How does strict determine if something has been legally defined and why doesn't importing a variable do so?
  • How can I satisfy strict in one package from another package?

The goal here is to avoid string eval. It's ok if a solution either requires a specific Perl version or XS. In fact, I'd love it if the solution required XS - I've been looking for an actual thing for me to get my feet wet in XS.


My criteria for good software:
  1. Does it work?
  2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

Replies are listed 'Best First'.
Re: How does strict determine if something is legally declared?
by diotalevi (Canon) on Jan 10, 2006 at 03:53 UTC

    How did you define $self? Define it harder next time. *{$pkg . "::self"} = gensym() works just find for this sort of thing. You could also alias your caller's $self to some $self known to your module if you plan to instantiate it for the class. See INGY's code for examples of him doing this kind of wierdness.

    *$tgt = \ $Class::self; *$tgt = Symbol::gensym(); *$tgt = \ "a constant";

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: How does strict determine if something is legally declared?
by Errto (Vicar) on Jan 10, 2006 at 04:19 UTC
    I believe what happens is that strict does a compile-time check to make sure the typeglob slot for that name and that type in the current package contains a valid reference (after checking that there's no in-scope my variable of that name). Here's a snippet from Exporter/Heavy.pm in Perl 5.8.6 that seems to do the meat of the work:
    *{"${callpkg}::$sym"} = $type eq '&' ? \&{"${pkg}::$sym"} : $type eq '$' ? \${"${pkg}::$sym"} : $type eq '@' ? \@{"${pkg}::$sym"} : $type eq '%' ? \%{"${pkg}::$sym"} : $type eq '*' ? *{"${pkg}::$sym"} : do { require Carp; Carp::croak("Can't export symbol: $type +$sym") };
    Shouldn't require XS AFAICT.
Re: How does strict determine if something is legally declared? (import)
by tye (Sage) on Jan 10, 2006 at 16:52 UTC

    There's a bit that gets set when you 'import' a variable and this bit tells 'strict' that the variable has been 'declared'. use vars simply 'imports' the variable.

    The heuristic that perl uses to detect when a variable is being 'imported' is to detect when the variable slot of a glob gets assigned to by code compiled into another package. Note that the importing has to be done before the code that uses the imported variable is compiled.

    > perl -w use strict; BEGIN { *x= \$foo::y; } print $x; Variable "$x" is not imported at - line 3. __END__ Global symbol "$x" requires explicit package name at - line 3. Execution of - aborted due to compilation errors. > perl -w use strict; BEGIN { package foo; *main::x= \$foo::y; } print $x; __END__ Name "foo::y" used only once: possible typo at - line 2. Use of uninitialized value in print at - line 3.

    - tye        

      Sorry for the necromancy, but I was wondering if anyone knows if and where this is documented? I've so far struck out on strict, perlmod, and perlref... did I just miss it, or is it not there?

      Update: As suggested by jdporter, now posted as a root node here: Logic for importing and strict vars? - Update 2: That thread didn't reveal any official documentation on the matter either.

        It's a good question. I strongly recommend you post a new SoPW root node.

        I reckon we are the only monastery ever to have a dungeon stuffed with 16,000 zombies.
        What? Strict docs or vars docs/source
Re: How does strict determine if something is legally declared?
by PodMaster (Abbot) on Jan 10, 2006 at 03:56 UTC
    'perldoc strict'
    "strict vars"
    This generates a compile-time error if you access a variable that wasn't declared via "our" or "use vars", localized via "my()", or wasn't fully qualified. Because this is to avoid variable suicide
    $self isn't localized via "my()", wasn't declared via "our" or "use vars", and it isn't fully qualified.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://522079]
Approved by diotalevi
Front-paged by johnnywang
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2024-04-25 13:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found