Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: reference to an undefined key

by stevieb (Canon)
on Oct 10, 2015 at 14:31 UTC ( #1144373=note: print w/replies, xml ) Need Help??


in reply to reference to an undefined key

You can't access attributes of an object before the object is created. It's like asking what the value of your bank account is, when you haven't even opened up an account yet.

You don't show where the $userId or $appName are coming from, but I suspect you'll be accepting them as params in your new() method.

What I would do here, is something like this, using an _init() method to do the lifting (untested). Note I've replaced $obj with $self, and extracted the variables for clarity, instead of just passing @_ around:

Update: The first half of my example doesn't perform properly. See AnomalousMonk's post below as to how it's broken. I've left it in as to not break context. Their reply has a fix.

use warnings; use strict; use Data::Dumper; package Test; sub new { my $self = bless {}, shift; my ($uid, $root, $app) = @_; my %attrs = $self->_init($uid, $root, $app); $self = \%attrs; return $self; } sub _init { my $self = shift; my ($uid, $root, $app) = @_; my %attrs; $attrs{Root} = $root; $attrs{UserDir} = $attrs{Root} . "Usr/$uid/"; $attrs{UserAppData} = $attrs{UserDir} . "$app", return %attrs; } package main; my $test = Test->new('steve', '/home/', 'perl'); print Dumper $test;

If you do want to do all the work in the constructor method, you can create the object up-front, then access all of its attributes before returning it:

sub new { my $obj = bless {}, shift; my ($uid, $root, $app) = @_; $obj->{Root} = $root; $obj->{UserDir} = $obj->{Root} . "Usr/$uid/"; $obj->{UserAppData} = $obj->{UserDir} . "$app", return $obj; }

-stevieb

Replies are listed 'Best First'.
Re^2: reference to an undefined key
by AnomalousMonk (Bishop) on Oct 10, 2015 at 15:39 UTC
        sub new {
            my $self = bless {}, shift;
            ...
            my %attrs = $self->_init($uid, $root, $app);
            $self = \%attrs;
            return $self;
        }

        sub _init {
            ...
            my %attrs;
            ...
            return %attrs;
        }

    Unfortunately, overwriting the blessed reference to an anonymous hash  $self with an unblessed reference to the  %attrs hash destroys the blessing an object reference needs. Your original code produces

    $VAR1 = { 'Root' => '/home/', 'UserDir' => '/home/Usr/steve/', 'UserAppData' => '/home/Usr/steve/perl' };
    from the  print Dumper $test; statement. (Update: The second definition of  new() returns a properly blessed object.)

    A minimal change to produce a properly blessed object reference might be something like

    c:\@Work\Perl>perl -e "use warnings; use strict; ;; use Data::Dumper; ;; package Test; ;; sub new { my $self = bless {}, shift; my ($uid, $root, $app) = @_; ;; return $self->_init($uid, $root, $app); ;; } ;; sub _init { my $self = shift; my ($uid, $root, $app) = @_; ;; $self->{Root} = $root; $self->{UserDir} = $self->{Root} . qq{Usr/$uid/}; $self->{UserAppData} = $self->{UserDir} . $app, ;; return $self; } ;; package main; ;; my $test = Test->new('steve', '/home/', 'perl'); print Dumper $test; " $VAR1 = bless( { 'Root' => '/home/', 'UserDir' => '/home/Usr/steve/', 'UserAppData' => '/home/Usr/steve/perl' }, 'Test' );
    (However, I find the whole  my $obj = bless { What => 'ever' }, shift; syntax a bit funky if the original goal is "to state the logic of the properties in clear." But that's another story...)


    Give a man a fish:  <%-{-{-{-<

      Nice catch, that's a big one I'm surprised I completely overlooked. Thanks :)

      Thanks for your reply and this reminded me something, do you have any feed back for my updates in the post ?
Re^2: reference to an undefined key
by exilepanda (Pilgrim) on Oct 10, 2015 at 16:39 UTC
    You can't access attributes of an object before the object is created.
    Yes, I know why my example won't work... but I am juz looking for if any work around to declare and define my object's properties in the style alike what I hope can happen.
    you can create the object up-front, then access all of its attributes before returning it...
    That's what I know I can deal with it so far, as shown in my original post ..so sad! =(
      ... I know why my example won't work... but I am juz looking for if any work around to declare and define my object's properties in the style alike what I hope can happen.

      The Monastery may harbor certain subtle and puissant monks who possess the dark art of accessing an object before that object is completely defined, but their ways should not be yours if you seek the Way of Clarity!

      If you wish "to state the logic of the properties in clear", I don't see why, combining the approaches of golux and stevieb with my own personal preferences, an approach like

      sub new { my $class = shift; my ($uid, $root, $app) = @_; my $obj = bless {} => $class; $obj->{Root} = $root; $obj->{UserDir} = "$obj->{Root}/Usr/$uid/"; $obj->{UserAppData} = "$obj->{UserDir}$app"; return $obj; }
      or maybe
      sub new { my $class = shift; my ($uid, $root, $app) = @_; return bless { Root => $root, UserDir => "$root/Usr/$uid/", UserAppData => "$root/Usr/$uid/$app", } => $class; }
      (both tested) would not be sufficiently clear. (Note the trailing / path separator is not needed on the  $root path specification.) Why be sad? Bask in the light of the Clear Path!

      Update: Just to be sure:


      Give a man a fish:  <%-{-{-{-<

      I agree completely with AnomalousMonk's post here: Re^3: reference to an undefined key. There *are* ways to do what you want (and we could definitely point them out), but it would involve using magic that isn't advised for standard use cases.

      Trying things out is one thing, but for code you're going to use, it's best to use idiomatic Perl that you, and anyone in the future can read easily at a glance six months after it is written.

      If you want to force your will upon a data structure creation, you'll want to look at symobolic references, and understand the symbol table. There's a decent intro here on PM: Of Symbol Tables and Globs.

      Again though, using magic to do things in a non-conventional way often leads to bugs that are "far away" or "at a distance" from the code that uses said magic, while leaving code that yourself, or others might not be able to comprehend in the future (even after a lot of review and tracing).

      With all those warnings stated, we don't learn how to force perl to do things unconventionally without pushing our limits of what we know.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (4)
As of 2020-04-01 06:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    To "Disagree to disagree" means to:









    Results (186 votes). Check out past polls.

    Notices?