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

Re: Calling module function from within a blessed module

by shmem (Chancellor)
on Jan 02, 2021 at 15:53 UTC ( #11126146=note: print w/replies, xml ) Need Help??

in reply to Calling module function from within a blessed module

This looks like you want do_soemthing() to act both as a method and a function.
If so, you need to check the first argument passed in. Inside that sub you would decide what to do either way.

sub do_something { my ($self, $param); $self = shift if ref $_[0] eq __PACKAGE__; # first argument is obj +ect $param = shift; # something... if ($self) { # method ... } else { # function ... } return $param; }

If it is a mere function internal to the class, it is good practice to prepend the function name with a dash. That's an informal convention to mark functions private to the module or class.

If it is strictly a method, then the answers of my fellow monks apply: $self->method(@args)

perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

Replies are listed 'Best First'.
Re^2: Calling module function from within a blessed module
by haukex (Bishop) on Jan 02, 2021 at 16:14 UTC
    $self = shift if ref $_[0] eq __PACKAGE__;

    Note that this unfortunately breaks for subclasses. Personally I prefer Scalar::Util's blessed and UNIVERSAL's isa.

    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 ref $_[0] eq __PACKAGE__; dd 'foo', $self, \@_; } sub bar { my $self = shift if defined blessed($_[0]) && $_[0]->isa(__PACKAGE__); dd 'bar', $self, \@_; } } { package Bar; use parent -norequire, 'Foo'; } Foo::foo('a'); # ("foo", undef, ["a"]) Foo::bar('b'); # ("bar", undef, ["b"]) my $f = Foo->new(); $f->foo('c'); # ("foo", bless({}, "Foo"), ["c"]) $f->bar('d'); # ("bar", bless({}, "Foo"), ["d"]) my $g = Bar->new(); $g->foo('e'); # ("foo", undef, [bless({}, "Bar"), "e"]) - oops! $g->bar('f'); # ("bar", bless({}, "Bar"), ["f"])

    Update: Added arguments to calls to make @_ more clear. Update 2: I guess in case the package name is "0", one could be doing defined blessed instead of just plain blessed, so I've updated the above, but since that's pretty unlikely, I'd say it's optional.

      Note that this unfortunately breaks for subclasses.

      This is true. Thanks for pointing that out, so I don't have to do that ;)

      The OP was really about calling syntax, and I sneaked in dual subs (method/function) and the __PACKAGE__ keyword, just to have that mentioned. Now you bring on subclassing, which is great - and a big field to tackle. Yes, the check for __PACKAGE__ is suitable for classes which aren't meant to be subclassed, won't be, or "I don't care about" modules, and more so: which strictly forbid subclassing.

      Your post is right, mine wasn't wrong, and from here we can go on exploring the whole perl OO fractal landscape... ;)

      perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      I guess in case the package name is "0"

      Much as it is good to consider edge cases, anyone who names their package "0" is going to asking for trouble!

        "... 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

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://11126146]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2021-03-01 05:20 GMT
Find Nodes?
    Voting Booth?

    No recent polls found