I thought I knew this, but it turns out I don't. The perlmod page claims that it's possible to reference the local variables of a package (or module). I have a situation where it would be really handy to do this rather than writing a zillion subs, one per variable. But my attempts to do it have all failed, convincing me that I just don't know the syntax.

Here's a test program that I made up out of the task, stripped down to the minimum:

This is running on "perl, v5.8.8 built for i486-linux-gnu-thread-multi", on a Debian box, but it fails the same way on a nearby FreeBSD and an OSX system. Also, I've spent the day going through zillions of variants of the code, using syntax that seems to be implied by various man pages. But nothing I've tried has worked at all.

What I'd like the above code to do is print the values of the package's variable $x without going through a "get" subroutine. It'd also be nice if I didn't actually need the setx function, though the current app doesn't require that.

It seems like I have to be missing something that should be really obvious. But I can't find any example of code doing this. I only find claims that it's doable, without any code showing the syntax.

(The preview wipes out the indentation in the example, and experimenting finds no way to make the indentation work. Sigh. ;-)

Declaring $x global doesn't make sense to me. Note the important point here: The code has more than one instance of the package. The "new A" command is done twice in my stripped-down example (and more than twice in the real program). Each instance of A needs its own local copy of its variables, because they hold different values in the different instances.

My original code did have the "use strict" and "use warnings" commands, and it loaded the package from a different file via a "use" command. I'd stripped these out in my attempt to produce a minimal example of what I hadn't been able to make work right. I tossed everything that didn't seem to be strictly related to the topic at hand, which was getting at a package's local variables from outside the package. The "man perlmod" page says this is possible: "You can refer to variables and filehandles in other packages by prefixing the identifier with the package name and a double colon: $Package::Variable. I did this in my example, and it doesn't work at all. I also tried '->' instead of '::', which failed in exactly the same way. I tried other likely syntaxes, which I won't bother people with because they also failed.

I'm not trying to get the usual lecture on good programming style, and I'm not about to post an entire program with thousands of lines; I'm trying to learn the correct syntax for one tiny little detail of the language.

(It's possible that perl doesn't permit a package declaration as in my example, inside the same source file as its invocation. But I did have it in a separate "A.pm" file originally, and it failed exactly as my stripped-down example does. Also, the package name was longer than "A" originally; I stripped that down, too. ;-)

Reducing your example to a minimal level is good and appreciated, but you still should always include the strict and warnings pragmas, in part because there are very important differences between what is allowed and not allowed.

One problem I see is that you're intermixing OO and functional style interfaces, which certainly can be done, as is is done in the CGI module, but shouldn't be done until you're fluent in both.

I need to work on cooking dinner, but when I have more time, I'll post one or two examples, unless someone else chimes in and provides those examples.

Assuming you want to stay with the OO interface, your first decision to make is do you want to have a single var that all objects share, or do you want an independent var for each object.

If you want a shared var, then you need to declare it as a global var and either access it via its fully qualified name. If you want an independent var for each object, then declare it as a lexical as part of the object.

The main reason I got into this is that the app I'm working on needs a lot of copies of the data structures, each with its own value for its local variables.

That was the main point of my stripped-down example. I called "new A" more than once, and stuffed the resulting references into the variables $A1 and $A2. Then I called $A1->setx() and $A2->setx() to stuff two different values into the two A objects' variables, both named $x (or $A::x presumably). Then I tried to use the values of these two different $x variables in the two instances of A.

If I can figure out how to do that right, I can probably implement what I'm trying to implement. The app I'm working on definitely needs to have many copies of its data structures, each describing a small part of the data, and linked together in complex ways. I'm having trouble finding documentation with coherent descriptions of how to do this right.

Your new sub needs to declare and assign default values to the vars (which is typically done via a hash ref) and then return the blessed hash ref. The new sub could also accept args, i.e., a hash ref, containing the desired values to be put into the object. Then you need to write accessor/mutator subs which retrieve and/or set the vars.

Then you need to write accessor/mutator subs which retrieve and/or set the vars.

So you're saying that what I asked about can't be done? ;-)

Adding the cpu cost of a function call to a simple variable reference is a rather large price to pay for something that, in most other language, has no time overhead. Thus, in C or C++, referencing a named field in a struct or class has no such overhead. The equivalent in perl seems to be accessing a named local variable in a package. If that requires a function ("method") call, it's a huge performance hit.

Also, if this is necessary, it sorta shoots down the primary reason for exporting variables. Of what value is exporting if one still needs access subs within the package to get/set those variables' values?

But I'll point out again that the "man perlmod" page disagrees; in its first paragraph it states "You can refer to variables and filehandles in other packages by prefixing the identifier with the package name and a double colon: $Package::Variable." The reason I asked my question in the first place was that I tried exactly this (where the $Package was the value returned by one of two "new A" calls), and it failed. I also tried it with '->' in place of '::', and that failed the same way. The call on each package's newx sub worked, in a sense, showing that my test package was defined and the syntax works for subs. It just fails for simple variables, contrary to what "man perlmod" says.

So did the "man perlmod" page lie to me about this? (If so, how can we punish the culprit that wrote that passage? ;-) If not, I'm at a loss as to where to go next.

But I'll read some more of those docs. Several of them have names that are new to me. I wonder where I might have found references to perltooc or perltoot? They're not names that I'd have guessed to try, and aren't mentioned in my "man perl" overview page.

I'm about to go into a meeting, so I can't address your comments in any detail until I get off work.

What I can say is that your understanding of the docs is not correct, in part because you're intermixing the meanings and usage of Perl OO and functional modules. Perl OO modules don't, or at least shouldn't, export anything. Functional modules do export their subs and in some cases their global vars.

The example I provided shows you how to access package global vars in a non OO module using their fully qualified name, as you want to do.

Ok, I'm home now, but need to keep this short because I need to cook dinner.

Quote

So you're saying that what I asked about can't be done? ;-)

No, that's not what I'm saying, but directly accessing/modifying a variable in a Perl OO module is discouraged in part because it breaks encapsulation.

Yes, executing a method call does have a very small overhead and in most cases that overhead is very negligible, unless you're planning on calling the same method millions of times to access the exact same data and if you're doing that, you have a problem with code logic.

Here is a minimal example of an OO module approach that does what you what.