Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Importing Symbol Tables

by moebius (Novice)
on Mar 27, 2002 at 00:08 UTC ( [id://154538]=perlquestion: print w/replies, xml ) Need Help??

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

Hello,

I am trying to better understand symbol tables wrt packages. I am working with a .pm and a .pl along the following lines:

a.pm:

package a;
$fred = 'test';

b.pl:

#!/bin/perl

use strict;
use a;

print "$fred\n";


At its basest, I would like to print $fred without the use of Exporter. I am working with the notion of a shared globals file, and I want to share this between multiple packages without the overhead and hassle of @EXPORT and the whole Exporter module.

It seems like there should be a way to import the symbol table via a simple mass typeglob, but as of this writing I have not been able to figure out how. I can get as far as being able to print $main::fred by doing '*main = *a::;', but I want to get this down even more (ie to being able to simply print $fred).

I can do this long hand but I'm considering globals files of 1000s of globals potentially. More of a theoretical exercise than anything.

Thanks in advance.

Replies are listed 'Best First'.
Re: Importing Symbol Tables
by VSarkiss (Monsignor) on Mar 27, 2002 at 00:30 UTC

    Your goals are a little contradictory. One thing Perl modules are meant to simplify is not throwing everything into the same namespace. That's why Exporter does it in a controlled fashion. As it points out,

    Exports pollute the namespace of the module user.
    The idea is to maintain some control over the level of sharing. But if you're going to have a thousand globals being shared, you're going against the grain of packages and modules (not to mention good programming practice).

    If all you're interested in is having your program read in a bunch of variables and values, don't use modules. Instead, you can use the do function to read them in, something like this:

    # stuff.pl $fred = 'foo'; $barney = 'bar'; # ...
    Later in the calling program:
    #! /usr/bin/perl # no strict unless "stuff.pl" my's everything. # (In which case all the vars will be lexical here.) do 'stuff.pl' or die "Couldn't read the stuff"; print $fred, "\n";
    Note: I'm not recommending you implement the above code. Rather, you may want to think about why you want to share so much data, and whether there's a better way to manage it.

Re: Importing Symbol Tables
by broquaint (Abbot) on Mar 27, 2002 at 00:34 UTC
    You could refer to it's by it's fully qualified name
    print $a::fred;
    As for importing all the variables in the symbol table you could do something like this
    package foo; $x = "a string"; @y = qw(an array); %z = qw(a hash); sub func1 { print "in foo:: \n" } 1; package main; foreach my $sym (keys %foo::) { *{"main::$sym"} = *{"foo::$sym"}; }
    This should import all the symbols of the foo symbol table into the main symbol table. But I imagine you have more constructive uses for symbol munging than polluting the main namespace, and of course you'll be using strict all the while ;-)
    HTH

    broquaint

Re: Importing Symbol Tables
by tadman (Prior) on Mar 27, 2002 at 00:37 UTC
    Using Exporter isn't really a huge hassle, since you can virtually auto-import if you declare them using something other than a whole whack of variables.

    Something to consider is using a global hash instead of a thousand global variables. Then you can have virtually unlimited access to "globals" without having to explicitly declare them.

    Further to that, if you really have thousands of "constants", these should probably come from a config file anyway, unless, of course, these are strictly related to the internals of the program.

    The more ambitious approach is to write your own import function and stuff references to your globals into the calling module. Consider:
    package Foo; our $a = "a"; our $b = "b"; sub import { my ($self) = @_; my ($caller_package) = caller; foreach (keys %{"${self}::"}) { *{"${caller_package}::$_"} = *$_; } }
    Now this will export everything that is exportable, that being those things declared with our instead of my.
      Thans to everyone for their comments thus far. Let me say that this is only an idle project that I am mussing with just to see how it all works. This will /not/ be production code...ever.

      My goal with this is mainly focused around better understanding the minutiae of packages and symbol tables. Controlling exports/imports between packages seems like an interesting test to me.

      Thanks again, and fear not, this project is a test only. You have given me much to ponder in the meantime. Keep em coming.

      Your humble apprentice.
Re: Importing Symbol Tables
by shotgunefx (Parson) on Mar 27, 2002 at 00:33 UTC
    No offense but mass importing of tons of variables is a really really bad idea. If you want to use globals, why not just give them their own short package name like so.
    package CFG;

    So at least looking at your source 3 months later it's clear what the hell $CFG:this is and you won't step on any variables in the scripts or vice/versa unintentionally.

    But to give you enough rope to hang yourself, you could do something like this.
    package other; $VAR = 'SCALAR'; @array = ('ARRAY') x 4; my @exports = qw ($VAR @array); sub import { no strict 'refs'; my $used_name = shift; # Remove the use name my $that_pack = caller(); foreach (@exports){ m/^([\@\$\*\&\%])(\w+)/; my ($t,$v) = ($1,$2); # Selectively assign to typeglobs. *{$that_pack.'::'.$v} = $t eq '@' && \@{$v} || $t eq '%' && \% +{$v} || $t eq '&' && \&{$v} || $t eq '$' && \$ +{$v} || $t eq '*' && \*{$v}; } } package main; other::import(); foreach (sort keys %main::){ print __PACKAGE__,"\:\:$_ = $main::{$_}\n"; } warn "\$VAR is $VAR"; warn join(", ",@array);

    Update:
    Fixed typo in code.
    Update:Fixed
    Ran into another snag. Seemed to work on win but no nix. Fixed. If anyone knows and easier way. Let me know.
    If you want to use this, use maintained code HERE

    -Lee

    "To be civilized is to deny one's nature."

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (8)
As of 2024-04-18 06:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found