in reply to encapsulation via compiler-checked symrefs

Actually, '__PACKAGE__' and '__LINE__' (and a few others) are special compiler directives. (They're not exactly directives, but close enough.) They're NOT variables, hence they don't fall under strict's purview, nor any other purview, for that matter.

The reason the spelling error is caught is because __PACKGE__ isn't a compiler directive in the way __PACKAGE__ is, hence the compiler doesn't know what to do about it.

Symbolic references are a valid programing technique. They let you do stuff that can't be done any other way, and that's one of Perl's selling points. I use them in an alternate way of implementing Perl OO.

But, do not use them unless you know why you shouldn't use them! They are an extremely dangerous technique and will get you into trouble. Unless they are used sparingly, you will not be able to maintain that code, nor will anyone else. You will not be able to prove your code works, espeically not after the first 10 bugfixes and enhancements. I don't care how much documentation you have - it won't be enough to cover all the cases.

------
We are the carpenters and bricklayers of the Information Age.

Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

  • Comment on Gods, don't try to justify using symrefs!

Replies are listed 'Best First'.
(tye)Re: Gods, don't try to justify using symrefs!
by tye (Sage) on Nov 05, 2001 at 22:57 UTC
    Actually, '__PACKAGE__' and '__LINE__' [...] are special compiler directives. [...] They're NOT variables, hence they don't fall under strict's purview, nor any other purview, for that matter.

    __PACKAGE__ doesn't bypass strict because it is some "special" "non-variable". It gets past strict because it is a compile-time constant (as I discussed in the thread that introduced this topic, self-referent hash for your packages).

    Some more examples:

    #!/usr/bin/perl -w my @strictures; BEGIN { require strict; if( ! grep /-v/, @ARGV ) { @strictures= "refs"; } } use strict @strictures; sub name1() { return "Foo::Bar" } sub name2 { return "Foo::Bar" } "Foo::Bar"->{key}= "value"; # No error print name1->{key},$/; # No error, prints "value" eval { print name2->{key},$/ # Fatal run-time error # Can't use string ("Foo::Bar") as a HASH ref while "strict refs" } or warn $@; { package Foo::Bar; print __PACKAGE__->{key},$/; # No error, prints "value" } eval q{ sub name3() { return "Foo" } sub name4 { return "Foo" } "Foo"->{key}= "bar"; # If only strict 'refs', then prints "bar" w/ no errors # (-v)Global symbol "%Foo" requires explicit package name print name3->{key},$/; # If only strict 'refs', then prints "bar" w/ no errors # (-v)Global symbol "%Foo" requires explicit package name eval { print name4->{key},$/; # Can't use string ("Foo") as a HASH ref while "strict refs" } or warn "Line ",__LINE__,": $@"; eval q{ package Foo; print __PACKAGE__->{key},$/; # Use of uninitialized value in print 1; } or warn "Line ",__LINE__,": $@"; } or warn "Line ",__LINE__,": $@";
    Which boils down to some interesting things:

    • Compile-time string contants that contain "::" can be used as symbolic references even under use strict "refs".
    • Compile-time string contants that don't contain "::" generate a fatal "Global symbol requires explicit package" error under use strict "vars".
    • The (horrid) __PACKAGE__-> trick, when used in a package whose name contains no "::", fails under use strict "vars" and tries to access a hash whose name is __PACKAGE__."::".__PACKAGE__ (instead of the usual name of __PACKAGE__).

    Which makes me swing more toward the opinion that compile-time constant strings getting past use strict "refs" is simply a bug (and should put one more nail in the coffin of this hack).

    Update: BTW, the reason that compile-time string constants get past use strict "refs", is (as I suspected) because the resulting code gets compiled as if the string were entered "bare":

    perl -MO=Deparse -e "'Foo'->{key}= 'value'" $Foo{'key'} = 'value'; -e syntax OK

            - tye (but my friends call me "Tye")