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

When I make new subs in my niffty perl modules, the first argument is sometimes a pointer to the module/object ... whatever, I really don't know exactly.

I need a cool_majik_check to see if the first arg is infact a pointer to itself or not. Sometimes I like to call a function from inside the module which makes it hard to tell.

sub my_funky {
    shift if cool_majik_check;
    my ($arg1, @others) = @_;

    return "What a stup'd funky";
}

Replies are listed 'Best First'.
Re: so simple
by merlyn (Sage) on Jun 14, 2000 at 22:00 UTC
    The first arg to a subroutine is either a string (a class {package} name) or a reference (an object {blessed reference}) when you use the arrow invocation, or when you fake such.

    There's no sure test to determine if the first arg is Perl-provided or caller-provided. Thank goodness for that. So, you'll just have to be consistent, or else you'll end up writing the same kind of scary code that pervades (and slows down) CGI.pm on every call.

    -- Randal L. Schwartz, Perl hacker

Re: so simple
by gnat (Beadle) on Jun 14, 2000 at 22:27 UTC
    The easiest solution is to not have functions that do double duty as methods. Either don't use objects (probably not reasonable) or don't use normal function calls. Make all your subroutines be methods, then say:
    sub some_public_subroutine {
      my $objref = shift;
    
      #blah blah
      $objref->some_private_sub("arg1", "arg2", "...");
    
    }
    
Re: so simple
by Perlmage (Acolyte) on Jun 15, 2000 at 16:26 UTC

    However...

    If you really want to check to see if the sub is being invoked as a method or a function, you can use the following:

    #!/usr/bin/perl package myClass; use strict; use warnings; ### Pure-cheese useless constructor sub new { bless {}, __PACKAGE__ } ### Bimodal sub sub someFunction { my $self = shift if @_ && UNIVERSAL::isa( $_[0], 'UNIVERSAL' ); my $otherArg = shift; print "Called as ", defined $self ? "method" : "function", " with '$otherArg' argument.\n"; } package main; use strict; use warnings; # Invoked as a function myClass::someFunction( "function thingie" ); # Invoked as a method my $testThingie = new myClass; $testThingie->someFunction( "method thingie" ); # It even works invoked as a static method myClass->someFunction( "static method thingie" );


    It basically just uses the mother of all superclasses ('UNIVERSAL') to check for object/class-ness. If a thing can be said to inherit from UNIVERSAL (have UNIVERSAL in its @ISA), then it can be assumed to be either a blessed reference (aka object), or the name of a class. What this function doesn't test is to see if the package that the first arg belongs to is actually your own. This is left as an excercise for the reader. =:)

    Like Randal said, though: Once you venture down that path, your interface forever must support such nastiness, which can only lead to grief and ruin.