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

I tend not to use "our" vars, but rather other ways to get the job done. Today I thought I'd give our vars a spin, and couldn't get perl to do what I wanted it to do. I could get the "our" var to print when I used the package name, but I couldn't access it from a reference to the package.
use strict; use warnings; package foo; # this is how I usually do it. use fields qw(bar); # can't accomplish what I want with our vars alone. #As the answerers explained, I need a helper function to do this. # I guess using fields is a way to get the same effect with a, what do + you call it, syntactic artificial sweetener... our $bar = "10\n"; no warnings 'deprecated'; #otherwise get warnings because fields uses +pseudohash sub new { defined( my $self = shift) or die "no object"; $self = fields::new($self); $self->{bar} = 10; return $self; } package main; my $foo_obj = foo->new(); #print '$fooobj::bar: ' . $foo_obj::bar . "\n"; # I want this to prin +t 10, but it's an uninitialized var. So commented out. print '$foo_obj-{bar}: ' . $foo_obj->{bar} . "\n"; #this prings 10 usi +ng fields print '$foo::bar: ' . $foo::bar . "\n"; # this prints 10 without the p +ackage name
What am I doing wrong?

(This was prompted by musing on my answer to arunvelusamy's question earlier today at [ooperl] calling reference to a annonymous sub)

UPDATE: Well, as the ever-helpful BUU and sauoqhave pointed out, it appears this was a fairly hare brained idea to begin with. FWIW, I have updated the above code to also use fields, which is what I customarily do to accomplish this task, as neither of the answerers mentioned this particular way of getting the mission accomplished, and I rather like fields.

UPDATE 2: In answer to sauoq, no, my question didn't change. The only change was I integrated use fields just now. Thanks again for putting up with my harebrainedness ;)

Replies are listed 'Best First'.
Re: How do you get an "our" var out of an object?
by BUU (Prior) on Nov 07, 2005 at 10:26 UTC
    What you're doing wrong is expecting it to work =].

    our declares a variable that lives in the current package. (Well, actually it creates a lexical alias to the package variable, but same difference). In the example you have, you're trying to use 'foo_obj' as the package name, because that's how the 'package::variable' syntax works. Even when you have the object, you need the package name the object is blessed in to to access the variables in the package name.

    For example, ref returns the package name and you can fairly easily use that to access package variables, but in general this is considered a bad idea. You can always use class methods as accessors.
Re: How do you get an "our" var out of an object?
by sauoq (Abbot) on Nov 07, 2005 at 10:45 UTC

    Update: Did this question change? I swear that, when I was replying to it, it implied you wanted to get rid of your "our variables"... (I did just wake up though, so maybe I was fuzzy-headed.)

    Upon reading it now, it seems you just want a method which accesses a class variable...

    package Foo; our $bar = 'some default'; sub new { bless {} } sub bar { shift; $bar = shift if @_; $bar } package main; my $obj = Foo->new; print $obj->bar, "\n"; $obj->bar('something else'); print $obj->bar, "\n";

    Normally people use globals in part to avoid that sort of thing though. This is what you usually see:

    package Foo; our $bar = 'some default'; package main; print $Foo::bar, "\n"; $Foo::bar = 'something else'; print $Foo::bar, "\n";

    My original answer follows...

    I couldn't access it from a reference to the package.

    There are a number of ways but they boil down to basically the same thing. You can create a function or functions that will be used to access a lexical variable instead. The simplest is just to create an accessor class method:

    package Foo; my $bar = 'some default'; sub bar { $bar = shift if @_; return $bar; }
    You could provide a reference directly to the variable...
    package Foo; my $bar = 'some default'; sub bar_ref { return \$bar; }
    You can create an lvalue sub...
    package Foo; my $bar = 'some default'; sub bar : lvalue { $bar; }
    Which allows you to use it like this in your main program:
    print Foo::bar, "\n"; Foo::bar = 'something else'; print Foo::bar;
    You can limit the scope of the variable even further...
    package Foo; { my $bar = 'some default'; sub bar : lvalue { $bar } }
    So, there are a bunch of ways. The question is really why you want to... There's nothing necessarily bad about globals so long as you use them prudently and don't export them by default. If you have to do some sort of validation when the variable is set, then using the first of the above examples might make sense.

    -sauoq
    "My two cents aren't worth a dime.";