Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Importing an hash in a lexical scope

Reply
Thread Tools

Importing an hash in a lexical scope

 
 
Stefano Sabatini
Guest
Posts: n/a
 
      03-13-2007
Hi perl guys,

I would like to import an hash in a lexycal scope, so to be able
to access the values of the hash as they were lexicals variables
defined in the current lexycal scope.

For example I would like to define somewhere an hash like:
my %hash = (one => 1, two => 2, three => 3, four => 4);

and then be able to access the variables $one, $two, $three after
importing them:
{
# import the hash
...
print "One is $one, two is $two, three is $three and so on";
}

I successfully achieved to import an hash into the current package using
this incantation:

foreach (keys %hash) {
*$_ = \$hash{$_};
}

I also tried this:

{
my $keys_str;
foreach (keys %hash) { $keys_str.= "\$$_, " };

# here it evals the code in the evalled code lexycal environment, which is
# (unfortunately) not the current lexycal environment, so the
# lexycal binding is immediately discarded

eval "my ($keys_str)";

no strict;
# this cause the creation of global (package) variables
# and don't warn 'cause of the no strict pragma
foreach (keys %hash) {
eval "\$$_ = $hash{$_};";
}
}

but after some debugging and thinkering I realized it can't work (as
explained in the comments above).

So I'm thinking maybe it's not possible at all to achieve my goal, or
maybe I can't simply see how.

Any help or suggestion will be highly appreciated.

Many cheers
--
Stefano Sabatini
Linux user number 337176 (see http://counter.li.org)
 
Reply With Quote
 
 
 
 
Uri Guttman
Guest
Posts: n/a
 
      03-13-2007
>>>>> "SS" == Stefano Sabatini <(E-Mail Removed)> writes:

SS> I would like to import an hash in a lexycal scope, so to be able
SS> to access the values of the hash as they were lexicals variables
SS> defined in the current lexycal scope.

SS> For example I would like to define somewhere an hash like:
SS> my %hash = (one => 1, two => 2, three => 3, four => 4);

SS> and then be able to access the variables $one, $two, $three after
SS> importing them:
SS> {
SS> # import the hash
SS> ...
SS> print "One is $one, two is $two, three is $three and so on";
SS> }

that is a very foolish idea in several ways. first, you can't import
into lexical scope, only into the symbol table. second, the whole point
of hashes is not to have individual variables for each value when they
are related. what you are asking for is symbolic (as i said, lexical
won't even work) references which are a very bad idea.

SS> I successfully achieved to import an hash into the current package using
SS> this incantation:

SS> foreach (keys %hash) {
SS> *$_ = \$hash{$_};
SS> }

was use strict enabled? won't work then.

SS> I also tried this:

SS> {
SS> my $keys_str;
SS> foreach (keys %hash) { $keys_str.= "\$$_, " };

SS> # here it evals the code in the evalled code lexycal environment, which is
SS> # (unfortunately) not the current lexycal environment, so the
SS> # lexycal binding is immediately discarded

SS> eval "my ($keys_str)";

nasty.

SS> no strict;
SS> # this cause the creation of global (package) variables
SS> # and don't warn 'cause of the no strict pragma
SS> foreach (keys %hash) {
SS> eval "\$$_ = $hash{$_};";
SS> }
SS> }

again nasty.

SS> but after some debugging and thinkering I realized it can't work (as
SS> explained in the comments above).

why do you think you need to do this? will it make your code much
cleaner or easier? since you MUST know the names of the hash keys in
advance since you want to refer to them by name (in whatever scope), why
would a general import help? all you save would be typing the name of
the hash.

SS> So I'm thinking maybe it's not possible at all to achieve my goal, or
SS> maybe I can't simply see how.

you can't in a lexical scope. it is dumb in the symbol table.

SS> Any help or suggestion will be highly appreciated.

don't do it at all. use the hash as it is. you won't gain much at all
doing what you want. you may think you do but there are other
ways. since you MUST know the names you will be using, why not just do
this:

my $first = $hash{first} ;

and so on. do that in the tightest scope just before where you use
$first. and if you only use $first one time then don't even do that,
just use the hash.

uri

--
Uri Guttman ------ http://www.velocityreviews.com/forums/(E-Mail Removed) -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
 
Reply With Quote
 
 
 
 
Stefano Sabatini
Guest
Posts: n/a
 
      03-14-2007
Hi Guri, and thanks for your reply.

On 2007-03-13, Uri Guttman <(E-Mail Removed)> wrote:
>>>>>> "SS" == Stefano Sabatini <(E-Mail Removed)> writes:

>
> SS> For example I would like to define somewhere an hash like:
> SS> my %hash = (one => 1, two => 2, three => 3, four => 4);
>
> SS> and then be able to access the variables $one, $two, $three after
> SS> importing them:
> SS> {
> SS> # import the hash
> SS> ...
> SS> print "One is $one, two is $two, three is $three and so on";
> SS> }
>
> that is a very foolish idea in several ways. first, you can't import
> into lexical scope, only into the symbol table. second, the whole point
> of hashes is not to have individual variables for each value when they
> are related. what you are asking for is symbolic (as i said, lexical
> won't even work) references which are a very bad idea.
>
> SS> I successfully achieved to import an hash into the current package using
> SS> this incantation:
>
> SS> foreach (keys %hash) {
> SS> *$_ = \$hash{$_};
> SS> }
>
> was use strict enabled? won't work then.


well, I was using no strict there.
is there a better way to import an hash in the main package (without
disabling the strict pragma), or is this a bad practice to avoid?

>
> SS> I also tried this:
>
> SS> {
> SS> my $keys_str;
> SS> foreach (keys %hash) { $keys_str.= "\$$_, " };
>
> SS> # here it evals the code in the evalled code lexycal environment, which is
> SS> # (unfortunately) not the current lexycal environment, so the
> SS> # lexycal binding is immediately discarded
>
> SS> eval "my ($keys_str)";
>
> nasty.
>
> SS> no strict;
> SS> # this cause the creation of global (package) variables
> SS> # and don't warn 'cause of the no strict pragma
> SS> foreach (keys %hash) {
> SS> eval "\$$_ = $hash{$_};";
> SS> }
> SS> }
>
> again nasty.


well, I agree, and indeed it was just an experiment, and I'd think twice
before to put it in production code.

> SS> but after some debugging and thinkering I realized it can't work (as
> SS> explained in the comments above).
>
> why do you think you need to do this? will it make your code much
> cleaner or easier? since you MUST know the names of the hash keys in
> advance since you want to refer to them by name (in whatever scope), why
> would a general import help? all you save would be typing the name of
> the hash.


I have this problem. There is portion of user defined code (via a
code reference) loaded at run-time, and an hash containing options values
used in that code, which again is defined by the user at run-time.

I would like the user to use all the variables defined in the hash as
they were defined as regular variables in the code environment, rather
than hash entries.

For example:

my %options= (name => "John Doe",
programming_language_used => "Perl",
vice => "nastiness");


then I would like to access these values in the code in this way:

my $funref = {
print "My name is $name, I'm programming in $programming_language_used, ",
"my vice is $vice";
}

rather than like this:
my $funref = {
# $options is a reference to the options hash
my ($options) = @_;
print "My name is $options->{name}, ",
"I'm programming in $options->{programming_language_used}, ",
"my vice is $options->{vice}";
}

but, basing on what you said, I see it would be better (easier on the
programmer, *safer*) the latter, even if it is sligthly more prolisse.

> SS> So I'm thinking maybe it's not possible at all to achieve my goal, or
> SS> maybe I can't simply see how.
>
> you can't in a lexical scope. it is dumb in the symbol table.
>
> SS> Any help or suggestion will be highly appreciated.
>
> don't do it at all. use the hash as it is. you won't gain much at all
> doing what you want. you may think you do but there are other
> ways. since you MUST know the names you will be using, why not just do
> this:
>
> my $first = $hash{first} ;
>
> and so on. do that in the tightest scope just before where you use
> $first. and if you only use $first one time then don't even do that,
> just use the hash.


OK, and many thanks for your knowledgable help.

as I said I was experimenting, but it seems that the solution I was
contriving wasn't a good one.

Cheers
--
Stefano Sabatini
Linux user number 337176 (see http://counter.li.org)
 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      03-14-2007
>>>>> "SS" == Stefano Sabatini <(E-Mail Removed)> writes:

>> was use strict enabled? won't work then.


SS> well, I was using no strict there.

that is the whole problem. strict is meant to stop you from doing evil
things.

SS> is there a better way to import an hash in the main package (without
SS> disabling the strict pragma), or is this a bad practice to avoid?

you haven't explained your bigger picture. why do you need to import the
hash? can you pass it as an argument by reference? can you remotely
access it via a sub or method? there are other ways to share data than
just importing. you seem to be stuck on only import and i see no reason
from you why that is so critical.

>>

SS> I also tried this:
>>

SS> {
SS> my $keys_str;
>> again nasty.


SS> well, I agree, and indeed it was just an experiment, and I'd think twice
SS> before to put it in production code.

good! you learned something!

>> why do you think you need to do this? will it make your code much
>> cleaner or easier? since you MUST know the names of the hash keys in
>> advance since you want to refer to them by name (in whatever scope), why
>> would a general import help? all you save would be typing the name of
>> the hash.


SS> I have this problem. There is portion of user defined code (via a
SS> code reference) loaded at run-time, and an hash containing options values
SS> used in that code, which again is defined by the user at run-time.

SS> I would like the user to use all the variables defined in the hash as
SS> they were defined as regular variables in the code environment, rather
SS> than hash entries.

that is bas as i have already explained. if they know the names of the
hash elements (not variables) they can use those directly. having them
automatically assigned to lexicals is not a win. let them do it in code
as i have shown you if they want that.

SS> print "My name is $name, I'm programming in
SS> $programming_language_used, ", "my vice is $vice";


SS> rather than like this:
SS> my $funref = {
SS> # $options is a reference to the options hash
SS> my ($options) = @_;
SS> print "My name is $options->{name}, ",
SS> "I'm programming in $options->{programming_language_used}, ",
SS> "my vice is $options->{vice}";
SS> }

so what is so bad about that? use a shorter name for $options if you
want. or use a templater (see Template::Simple on cpan for something
that will do that quickly and easily)

untested:

use Template::Simple ;

my $tmpl = Template::Simple->new() ;

my $in = <<INPUT ;
My name is [%name%],
I'm programming in [%programming_language_used%],
my vice is [%vice%]
INPUT

# put into $options the hash info as above (no code here for that)

print $tmpl->render( $options, $input ) ;

clean, fast, safe, no extra $options all around. $tmpl is reusable too.

SS> but, basing on what you said, I see it would be better (easier on the
SS> programmer, *safer*) the latter, even if it is sligthly more prolisse.

SS> So I'm thinking maybe it's not possible at all to achieve my goal, or
SS> maybe I can't simply see how.

your goal isn't worthy of being achieved as it is misguided. putting
lexicals into a remote scope would be dangerous even it could be
done. what if outside data set some other lexical that was used for some
external operation? a security hole a mile wide. php is famous for this
sort of thing (all cgi params automatically become variables, same nasty
concept).

as i have shown you here, you can use a templater. or have the users
assign their own lexicals. and there is nothing wrong with your basic
hash access as you know that works. why do you think your users need
such a minor extra little helper like your lexical idea? the other
solutions are almost as short and so much better in many ways.

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
 
Reply With Quote
 
Stefano Sabatini
Guest
Posts: n/a
 
      03-15-2007
On 2007-03-14, Uri Guttman <(E-Mail Removed)> wrote:
>>>>>> "SS" == Stefano Sabatini <(E-Mail Removed)> writes:

>
> >> was use strict enabled? won't work then.

>
> SS> well, I was using no strict there.
>
> that is the whole problem. strict is meant to stop you from doing evil
> things.
>
> SS> is there a better way to import an hash in the main package (without
> SS> disabling the strict pragma), or is this a bad practice to avoid?
>
> you haven't explained your bigger picture. why do you need to import the
> hash? can you pass it as an argument by reference? can you remotely
> access it via a sub or method? there are other ways to share data than
> just importing. you seem to be stuck on only import and i see no reason
> from you why that is so critical.


There is no particular reason for wondering about to import an hash. I
only stepped on the problem, I considerd the basic hash access method
and I wondered if it was possible to use that other method, that
seemed to slightly simplify the user code. Maybe I should have asked
myself if that was a good thing to do, and as you say maybe it's not
(for the same reasons you explained).

But I thought that was an interesting problem, I meant good to stretch
my own knowledge and awareness of the language.

And if you look at the problem from another point of view maybe my
question doesn't appear so much dumb: it's possible to import some
symbols from a package (that is an hash) into the current package,
it's possible (although disabling strict) to import a regular hash in
the current package as I showed, so maybe it could be possible to
import an hash in a lexycal environment.

> your goal isn't worthy of being achieved as it is misguided. putting
> lexicals into a remote scope would be dangerous even it could be
> done. what if outside data set some other lexical that was used for some
> external operation? a security hole a mile wide. php is famous for this
> sort of thing (all cgi params automatically become variables, same nasty
> concept).
> as i have shown you here, you can use a templater. or have the users
> assign their own lexicals. and there is nothing wrong with your basic
> hash access as you know that works. why do you think your users need
> such a minor extra little helper like your lexical idea? the other
> solutions are almost as short and so much better in many ways.
>


OK, indeed it's doesn't seems that bad, and I think I'll stick with
the basic hash access.

Many thanks.

Cheers
--
Stefano Sabatini
Linux user number 337176 (see http://counter.li.org)
 
Reply With Quote
 
Mumia W.
Guest
Posts: n/a
 
      03-16-2007
On 03/15/2007 09:49 AM, Stefano Sabatini wrote:
> On 2007-03-14, Uri Guttman <(E-Mail Removed)> wrote:
>>
>> you haven't explained your bigger picture. why do you need to import the
>> hash? [...]

>
> There is no particular reason for wondering about to import an hash. I
> only stepped on the problem, I considerd the basic hash access method
> and I wondered if it was possible to use that other method, that
> seemed to slightly simplify the user code. Maybe I should have asked
> myself if that was a good thing to do, and as you say maybe it's not
> (for the same reasons you explained).
>
> But I thought that was an interesting problem, I meant good to stretch
> my own knowledge and awareness of the language.
> [...]


I probably have no business posting this since the thread is basically
over, but I just got so curious that I had to see if it was possible,
and it is:

#!/usr/bin/perl
use strict;
use warnings;
use English qw(-no_match_vars);

my %h = (USER => 'han',
EMAIL => '(E-Mail Removed)',
PASSWORD => 'passWord');

$RS='';
while (my $custcode = <DATA>) {
my $code = join "",
map "my \$$_ = q{$h{$_}};\n", keys %h;
$code .= "\n$custcode\n";
# print $code;
eval $code;
if ($@) { die $@; }
}

__DATA__
local ($, , $\ ) = (' , ', "\n");
print "User Info:", $USER, $EMAIL, $PASSWORD;

print "My customer's email address is $EMAIL.\n";

use Digest::MD5 qw(md5_hex);
local $\ = "\n";
print "User ${USER}'s md5 password = ", md5_hex($PASSWORD);

__END__

In this program, each segment of customer code is separated by a blank
line, and there are three segments, so the while loop executes three
times. If you don't have Digest::MD5 installed, you get to see what
happens when "customer code" fails

However, as Uri said, using a hash is best. The difference between
${USER} and $h{USER} is nominal.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
hash of hash of hash of hash in c++ rp C++ 1 11-10-2011 04:45 PM
Re: Lexical scope vs. dynamic scope Xah Lee Java 0 02-26-2009 10:08 AM
python: lexical or dynamic scope? globalrev Python 3 05-14-2008 01:28 PM
Problem with Lexical Scope jslowery@gmail.com Python 18 12-17-2005 10:53 AM
Lexical Scope Matt Knepley Python 3 10-30-2003 06:45 PM



Advertisments