Accessing package data through variable

A

Amit Brahme

Hi,

I want to know if perl can do following thing.

------------------------------------------------------------------------
I've a package and some variables defined in it, like below, in file
lets say "junk1.pm".

******************
package junk1;
$foo = "xyz";
$abc = "123";
******************

In my program I write a code like

******************
require "junk1.pm";
$myrf = "junk1";
print $junk1::foo;
******************


What I want is: instead of using

print $junk1::foo;

I want to use $myrf (which is defined as "junk1") to access variable
"foo" in package junk1.

I tried

print ${$myrf}::foo;

but perl gives error for this that it found barework foo. Is there any
way I can do something like this?
 
P

Paul Lalli

Amit said:
I want to know if perl can do following thing.

------------------------------------------------------------------------
I've a package and some variables defined in it, like below, in file
lets say "junk1.pm".

******************
package junk1;
$foo = "xyz";
$abc = "123";
******************

In my program I write a code like

******************
require "junk1.pm";
$myrf = "junk1";
print $junk1::foo;
******************


What I want is: instead of using

print $junk1::foo;

I want to use $myrf (which is defined as "junk1") to access variable
"foo" in package junk1.

This is possible, but it's really time to ask your self *why* you'd
want to do such a thing? Why not just export the variable to your
namespace? Better yet, why not just use lexical variables and provide
set/get accessors?

${"${myrf}::foo"}

is the syntax I think you're looking for. Note that this will not work
under strict 'refs'. That alone should warn you away from this
approach.

Paul Lalli
 
T

Tad McClellan

Amit Brahme said:
I want to know if perl can do following thing.


It can, but doing the following is a really really bad idea...

------------------------------------------------------------------------
I've a package and some variables defined in it, like below, in file
lets say "junk1.pm".

******************
package junk1;
$foo = "xyz";
$abc = "123";
******************

In my program I write a code like

******************
require "junk1.pm";
$myrf = "junk1";
print $junk1::foo;
******************


What I want is: instead of using

print $junk1::foo;

I want to use $myrf (which is defined as "junk1") to access variable
"foo" in package junk1.


Why do you want to use $myrf to access variable "foo" in package junk1?

What is wrong with using $junk1::foo instead?

If we knew what real problem you are trying to solve, we may be
able to help solve it...


You are trying to use "symbolic references", which can lead
to extremely hard-to-find bugs.

There is almost always a better way to accomplish what you need
without symrefs, but we would need to know what you are really
trying to accomplish.

I tried

print ${$myrf}::foo;

but perl gives error for this that it found barework foo. Is there any
way I can do something like this?


print ${$myrf . '::foo'} # don't do this!

or

print ${"${myrf}::foo"} # don't do this either!
 
A

Amit Brahme

Thanks Paul.

The reason I want to use this structure is because I have multiple
packages and depending on certain user selection, data from one of the
packages need to be used. Since I didn't want to write code to select
which variable to be used, I was seeing if I can use user input directly
to reference the package I want to use.

Thanks and regards
Amit
 
A

Amit Brahme

Thanks Tad.

I've sent reply to Paul about reason why I was trying to do this. If you
can help me with a better way to handle this please do so.

Thanks and regards
Amit
 
R

robic0

Thanks Paul.

The reason I want to use this structure is because I have multiple
packages and depending on certain user selection, data from one of the
packages need to be used. Since I didn't want to write code to select
which variable to be used, I was seeing if I can use user input directly
to reference the package I want to use.
-<snipper>-
I only read this one paragraph from the entire thread and want to make a
comment on it.

I mean no disrespect at all but this spew was typed from your minds eye.
I see problems with you logic without even looking at your code. I use
"I" when "I" reply, but steer clear of "I" when posting code or reasoning.
The reason "I" don't use "I" is that "I" don't want to "prejudice" a logic
supposition by using "I". You know what "I" mean?
 
D

Dave Weaver

The reason I want to use this structure is because I have multiple
packages and depending on certain user selection, data from one of the
packages need to be used. Since I didn't want to write code to select
which variable to be used, I was seeing if I can use user input directly
to reference the package I want to use.

[ Please don't top-post (i.e. it's polite around here to put your reply
*after* the snippet of the post to which you're replying; that way a
reader sees the conversation in chronological order, top to bottom). ]

There's still no need for symrefs. You can simply import the variables
from the required package into your current namespace:

% cat t.pl
#!/usr/bin/perl
use strict;
use warnings;

our $foo;

my $module = shift;
require "$module.pm";
$module->import();

print "Foo is '$foo'\n";

% cat T1.pm
package T1;
use warnings;
use strict;
use base 'Exporter';
our @EXPORT = qw($foo);

our $foo = "Hello";

1;
% cat T2.pm
package T2;
use warnings;
use strict;
use base 'Exporter';
our @EXPORT = qw($foo);

our $foo = "world";

1;
% ./t.pl T1
Foo is 'Hello'
% ./t.pl T2
Foo is 'world'
 
A

Amit Brahme

Dave said:
The reason I want to use this structure is because I have multiple
packages and depending on certain user selection, data from one of the
packages need to be used. Since I didn't want to write code to select
which variable to be used, I was seeing if I can use user input directly
to reference the package I want to use.


[ Please don't top-post (i.e. it's polite around here to put your reply
*after* the snippet of the post to which you're replying; that way a
reader sees the conversation in chronological order, top to bottom). ]

Thanks Dave. I'll keep that in mind.
There's still no need for symrefs. You can simply import the variables
from the required package into your current namespace:

% cat t.pl
#!/usr/bin/perl
use strict;
use warnings;

our $foo;

my $module = shift;
require "$module.pm";
$module->import();

print "Foo is '$foo'\n";

% cat T1.pm
package T1;
use warnings;
use strict;
use base 'Exporter';
our @EXPORT = qw($foo);

our $foo = "Hello";

1;
% cat T2.pm
package T2;
use warnings;
use strict;
use base 'Exporter';
our @EXPORT = qw($foo);

our $foo = "world";

1;
% ./t.pl T1
Foo is 'Hello'
% ./t.pl T2
Foo is 'world'

What will happen if code imports the same module multiple times (which
might be the case for my code). Not sure if that can be a problem?

Thanks and regards
Amit
 
P

Paul Lalli

Amit said:
What will happen if code imports the same module multiple times (which
might be the case for my code). Not sure if that can be a problem?

Assuming you're using Exporter.pm's default import(), nothing will
happen on subsequent import() calls. If you write your own import()
method, all bets are off.

If your code could possibly be trying to import the same module
multiple times, allow me to suggest you need to re-think your code
design.

Paul Lalli
 
A

Anno Siegel

Paul Lalli said:
Assuming you're using Exporter.pm's default import(), nothing will
happen on subsequent import() calls. If you write your own import()
method, all bets are off.

On the other hand, with your own ->import it's up to you to make sure
it can be re-called without making a mess.
If your code could possibly be trying to import the same module
multiple times, allow me to suggest you need to re-think your code
design.

There's nothing wrong with importing the same module multiple times.

With some modules (warnings, strict, Carp, Exporter, ...) that is very much
the norm, though usually in different packages. A module like constant is
routinely loaded multiple times in the same package. Even with a standard
exporting module, you might want to load some basic stuff unconditionally,
and later decide whether to import specialized routines into the same
package.

Anno
 
X

xhoster

Another approach is:

print ${$::{"${myrf}::"}{foo}}

Despite that this one does work under strict refs, this approach is
probably even worse. But any port in a storm.

The reason I want to use this structure is because I have multiple
packages and depending on certain user selection, data from one of the
packages need to be used. Since I didn't want to write code to select
which variable to be used, I was seeing if I can use user input directly
to reference the package I want to use.


Why not have just one package with all of the data in it, stored in a hash
where the hash key corresponds to the package name under your current
design?

package one_package_to_bring_them_all_and_in_the_darkness_bind_them;
$hash{junk1}={foo=>'xyz', abc=>123};
$hash{junk2}={what => ever};


Xho
 
B

Brian McCauley

Another approach is:

print ${$::{"${myrf}::"}{foo}}

Despite that this one does work under strict refs, this approach is
probably even worse.

Yes, I agree with that. On the rare occasions where you've decided
that symrefs are justified you shouldn't try to pretend you are not
using them. Just put the code that needs them in a (minimal) block
with a "no strict 'refs'" pragma.
 
U

Uri Guttman

BM> Yes, I agree with that. On the rare occasions where you've decided
BM> that symrefs are justified you shouldn't try to pretend you are not
BM> using them. Just put the code that needs them in a (minimal) block
BM> with a "no strict 'refs'" pragma.

total agreement. and this is a good place to plug my rules on
symrefs. first off using symrefs is just using the perl symbol table as
your data structure. the reason you want to mung with the symbol table
is to actually deal with symbols, not to mung regular data. using a
proper hash and references is:

faster - symbol table access is slower than plain hash
access

safer - no chance of symbol clobbers or action at a
distance

more flexible - you can pass around your own isolated
structures

more secure - you can control access to your data

so the rule is, never use symrefs unless your goal is to actually mung
the symbol table. and most symbol table operations (including common
exporting) is installing subs so if you aren't installing subs (or other
globals), don't use symrefs.

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top