in reply to Re^3: Calling module function from within a blessed module
in thread Calling module function from within a blessed module

"... anyone who names their package "0" is going to asking for trouble!"

Naming a package 0 is a fatal, compilation error:

$ perl -e 'package X;' $ perl -e 'package 0;' syntax error at -e line 1, near "package 0;" Execution of -e aborted due to compilation errors.

The problem is likely to occur where, in some code completely separate from yours, someone writes '$x->your_method()' when, perhaps, '$y->your_method()' was intended.

I had some difficulty coming up with an example. Here's some valid, albeit highly contrived, code to demonstrate the concept.

I've used a common alias of mine to show code validity:

$ alias perle alias perle='perl -Mstrict -Mwarnings -Mautodie=:all -MCarp::Always -E +'
$ perle ' package X { use Scalar::Util "blessed"; sub new { bless {}, __PACKAGE__; } sub meth1 { say "meth1: [", ref $_[0], "]" } sub meth2 { say "meth2: [", blessed $_[0] // "undef", "]" } sub meth3 { say "meth3: [", defined blessed $_[0], "]" } }; package main; my $x = 0; my $y = X::->new(); $x->X::meth1(); $x->X::meth2(); $x->X::meth3(); $y->X::meth1(); $y->X::meth2(); $y->X::meth3(); ' meth1: [] meth2: [undef] meth3: [] meth1: [X] meth2: [X] meth3: [1]

The 'package X;' is intended to represent your code; the 'package main;' (although quite superfluous here) is intended to represent "some code completely separate from yours".

— Ken

Replies are listed 'Best First'.
Re^5: Calling module function from within a blessed module
by haukex (Archbishop) on Jan 02, 2021 at 19:48 UTC
    Naming a package 0 is a fatal, compilation error ... The problem is likely to occur where, in some code completely separate from yours, someone writes '$x->your_method()' when, perhaps, '$y->your_method()' was intended.

    Another example might be auto-generated package names (though if such code generated a package named "0", one could question the sanity of that choice...)

    use warnings; use strict; { package Foo; use Data::Dump; use Scalar::Util qw/blessed/; sub new { return bless {}, shift } sub foo { my $self = shift if blessed($_[0]) && $_[0]->isa(__PACKAGE__); dd 'foo', $self, \@_; } sub bar { my $self = shift if defined blessed($_[0]) && $_[0]->isa(__PACKAGE__); dd 'bar', $self, \@_; } } { no strict 'refs'; @{"0::ISA"} = ('Foo') } my $x = bless {}, '0'; $x->foo(); # ("foo", undef, ["0=HASH(0x561239194f3e)"]) $x->bar(); # ("bar", "0=HASH(0x561239194f3e)", [])

      The general idea I trying to get across — and, perhaps, didn't explain sufficiently well — was that problems are less likely to occur from a hard-coded package name, but rather from accidentally using an incorrect variable; the likelihood of which is exacerbated by poorly chosen (especially single-letter) variable names.

      The type of scenario I envisaged, involved $x being used for some purpose, and ultimately ending up with a value of zero. Later in the code, a variable to represent either an X class, or an object thereof, was wanted. As $x was already taken, the coder chose the next available, single-letter variable, $y.

      Subsequently, and paraphasing your example, the intuitive but incorrect @{"${x}::ISA"} and bless {}, $x was used; when, of course, the unintuitive yet correct @{"${y}::ISA"} and bless {}, $y was needed.

      Possibly getting a little off-topic (and hopefully not heading towards too much of a rant) but, in the main, meaningful names should be used, and single-letter names should be generally avoided. There are a few well-known examples where single-letter names are fine; e.g. sort { $a <=> $b } and in the limited scope of for my $i (0..$#ary). I also use them in one-liners and short example code. Other than that, I always aim to use meaningful names.

      — Ken

        The general idea I trying to get across — and, perhaps, didn't explain sufficiently well — was that problems are less likely to occur from a hard-coded package name, but rather from accidentally using an incorrect variable; the likelihood of which is exacerbated by poorly chosen (especially single-letter) variable names.

        Sorry, I probably should have said: I think your example is good, I was just giving another scenario :-)

Re^5: Calling module function from within a blessed module
by shmem (Chancellor) on Jan 02, 2021 at 19:50 UTC

    Heh...

    perl -E ' $o = bless \$o, 0; *{"0::barf"} = sub {say "woof $_[1]"}; $foo = 0; $foo->barf("warf"); say $o; $o->barf("chrrr, wuff!"); 0->barf("what?")' woof warf 0=REF(0x1267880) woof chrrr, wuff! woof what?

    This is part of perl's flexibility I dearly love, and that shouldn't go away. I could - if there was a need for it! - even make integers into packages and let them have their own methods. Although those integers are strings as package names, perls builtin conversions just dwim.

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
Re^5: Calling module function from within a blessed module
by LanX (Saint) on Jan 03, 2021 at 23:57 UTC
    I didn't read the thread and can't comment on the discussion and motivation, but this caught my eye:

    > Naming a package 0 is a fatal, compilation error:

    Yeah but like many things in Perl this can be fabricated.

    Packages are just entries with trailing :: in main's STASH.

    And its possible to alias STASH entries via type globs.

    So create a temporary package, alias it to "0::" and delete the temp package.

    Mission accomplished! :)

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

    PS: Please don't crucify me now ... I haven't met my Maria Magdalena yet!