Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Variable Name Mistery. Who calls?

by porta (Sexton)
on Oct 25, 2006 at 16:26 UTC ( [id://580619]=perlquestion: print w/replies, xml ) Need Help??

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

Hi to all. I'm a perl rookie and I started to struggle creating my own modules. I'm having a question that I cannot answer by myself and I ask for your Wisdom to trow some light on my dilemma.
Lets say that I create a module Foo.pm, which has "new" sub.
package Foo; sub new { my ($class) = @_; my $self = {}; bless $self, $class; }
And, I have my script test.pl which has:
use Foo; my $one = Foo->new; my $second = Foo->new;
And my question is: Is there a way that I can, inside Foo.pm, know the name of the variable that I'm using on test.pl?
Lets say I want to create a sub on Foo.pm that just returns the name of $one or $second.
Note that I need this to be able to catch and display my own custom warnings on Foo.pm and I want to give the name of the variable that caused the warning when printing on screen the warning message.
I hope my question is clear enough. I'm not a good english speaker so please excuse any error on the writing. Thanks in advance for any help or comment about this.

Replies are listed 'Best First'.
Re: Variable Name Mistery. Who calls?
by ikegami (Patriarch) on Oct 25, 2006 at 16:32 UTC

    Objects encapsulate data. This can include their name/id.

    package Foo; sub new { my ($class, $id) = @_; my $self = { id => $id }; return bless $self, $class; } sub method { my ($self) = @_; ... if (...something went wrong...) { warn("$self->{id} rotted into a pile of mush\n"); } ... }
    use Foo; my $one = Foo->new('one'); my $second = Foo->new('two');

    ( If what you want to do is possible, it'll be hard, fragile and error prone. That's why I suggested this alternative. )

      You could also modify this to save information from caller and store off the filename and line number where the constructor was called from if a more meaningful name isn't provided (of course I don't know offhand how that'd behave with subclasses . . .).

Re: Variable Name Mistery. Who calls?
by sauoq (Abbot) on Oct 25, 2006 at 17:17 UTC

    Maybe you can reliably do this with some B magic or something but there's no simple solution that I know of. For instance, consider the following code...

    package P; sub new { bless {} } sub print_my_var { ... } package main; my $p = P->new(); my $q = $p; *r = $p; $p->print_my_var(); $q->print_my_var(); $r->print_my_var();
    With $p, $q, and $r as three different names for the same object, how would you want that to behave?

    -sauoq
    "My two cents aren't worth a dime.";
      What I want is: I'm working on a module to allow me create objects on the fly (I know there are a bunch of cpan modules that does exactly the same and better, but I was wondering how would that be, and also considered that a good learning experience) The point is that I'm using something like this (On my main class):
      sub AUTOLOAD { my $_call = our $AUTOLOAD; $_call =~ s/.*:://; my $self = shift; my $param = shift; ... $self->{$_call} = $_param || return $self->{$_call}; }
      So far, so good. But the problem is, that at some point, when I initialize a 'new' object, I define for it a list of available parameters, which will be then used as that object method. So, what I want is to raise a warning when I try to do something like
      my $o = Foo->new(); #create new object $o->Available_Param_List(["one", "two"]); #methods that should be avai +lable to $o $o->one('this will work ok'); $o->nope('this should print a warn on saying that nope is not availabl +e for $o');
      I want to avoid things like passing the var name to the constructor function or things like that... Thats why I been thinking that *maybe* there was a way to know the name of the variable that called to a package.

        The traditional message is

        Can't locate object method "nope" via package "Foo" (perhaps you forgo +t to load "Foo"?) at file.pl line 4.

        Why won't the following suffice?

        Can't locate object method "nope" (perhaps you forgot to specify "nope +" to Available_Param_List) at file.pl line 4.

        Chances are you won't be calling nope more than one time per line, so you'll know exactly which object is giving the error.

        Use Carp's croak to make the message appear to originate from the calling line.

        #!/usr/bin/perl my $o = Foo->new(); $o->available_methods([ qw/one two/]); $o->one("This will work\n"); $o->two("This will work as well\n"); $o->three("This won't work\n"); package Foo; use Carp; my %Objs; sub new { my $self = {}; $Objs{$self} = {}; bless $self, shift; } sub available_methods { my($self,$methods_ref) = @_; $Objs{$self}{methods} = $methods_ref; } sub DESTROY { my $self = shift; delete $Objs{$self}; } sub AUTOLOAD { my $_call = our $AUTOLOAD; $_call =~ s/.*:://; my $self = shift; my $param = shift; if(grep /$_call/,@{ $Objs{$self}{methods} }) { print $param; } else { carp("Couldn't execute $_call\n"); } }
        my $param = shift; ... $self->{$_call} = $_param || return $self->{$_call};
        I assume $param and $_param were supposed to be the same. That's a little obfuscated, and doesn't allow setting parameters to false values. A more typical way to do it is:
        # (after shifting everything but param) if (@_) { return $self->{$_call} = shift; } else { return $self->{$_call}; }
Re: Variable Name Mistery. Who calls?
by cephas (Pilgrim) on Oct 25, 2006 at 17:27 UTC
    More likely you are looking for carp and croak from the Carp module.
Re: Variable Name Mistery. Who calls?
by gam3 (Curate) on Oct 25, 2006 at 23:45 UTC
    If you take ikegami's idea one more step. You can enforce the variable name and save a little typing. However you get odd syntax.
    { package Foo; sub new { my ($class, $id) = @_; my $self = { id => $id }; my ($package) = caller; ${$callpkg."::".$id} = bless $self, $class; undef; } sub method { my ($self, $name) = @_; print $self->{id}, "\n"; } } Foo->new('one'); Foo->new('second'); $one->method; $second->method;
    This does not have the same syntax, but does get you the same result with about the same number of words. And you get pretty good error detection.
    -- gam3
    A picture is worth a thousand words, but takes 200K.
      The problem with your solution is that it is installing global package variables into the calling module (or main script). Normally - and also in ikegami's post - you use local my variables for objects!

      -- Hofmator

      Code written by Hofmator and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Variable Name Mistery. Who calls?
by Anonymous Monk on Oct 25, 2006 at 17:26 UTC
    warn "Error: \$self ..\n"; warn "Error: \$_[0] ..\n";
Re: Variable Name Mistery. Who calls?
by DrHyde (Prior) on Oct 26, 2006 at 09:37 UTC
    For all practical purposes, you can't do that. Nor do you want to.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (2)
As of 2024-07-25 19:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.