I'm no guru, but I'll give you some reasons why not. Here's three off the top of my head:
- Soft references are global
- What if $var1 == 'con' and $var2 == 'fig' - and $config is a very important variable?
- What if a later programmer (like you?) wanted to add a variable named $config later? He would have to check to make sure that 'config' was not a valid value of $var1.$var2
Don't just listen to me (or sauoq or fruiture or Abigail-II above), go to http://perl.plover.com and read what dominus thinks of using a variable as a variable name - Part
1, 2, and 3
| [reply] [d/l] [select] |
I keep all my import variables in a hash for safe keeping.
I let these dynamic variables as listed above exist in the main root hash environment (if you could call it that).
so there's %ENV, %GET, %POST, %IP, %DEFAULTS, and %DATABASE.
This is safer anyway. measure twice, declare once.
I'm still not saying i'm right, but anti-soft reference arguments don't float.
Maybe it's the hash.
I wonder if a reminder of the beauty of 'local' would also help the case here.
After reading dominus's arguments against soft references i still remain. One could spend hours telling you how dangerous using perl is when you use the shebang line.
Then, i thought of 'local' and did a test...
Error 500 in the face.
This doesn't work.
#!/usr/bin/perl
&tryLocal("name=james&color=red&age=12");
exit;
####################
sub tryLocal{
local $in = $_[0];
@in = split(/\&/,$in);
foreach $li(@in){
($lname,$lvalue)=split(/\=/,$li);
local $$lname = $lvalue;
}
}################# end tryLocal
This works.
#!/usr/bin/perl
&tryLocal("name=james&color=red&age=12");
exit;
####################
sub tryLocal{
local $in = $_[0];
@in = split(/\&/,$in);
foreach $li(@in){
($lname,$lvalue)=split(/\=/,$li);
$$lname = $lvalue;
}
}################# end tryLocal
Which leads me to say. I was wrong.
As you fall in love with local
(which i have been doing all summer),
you must abandon my old ways.
Create your hash and check $TEMP{$passcode}
instead of $passcode.
|
| [reply] [d/l] [select] |
I let these dynamic variables as listed above exist in the main root hash environment (if you could call it that).
No, you cant call it that. Or at least if you can then you can also call it "brown pudding". :-)
Dynamic variables exist in a package. So what you mean is that they are members of the package "main".
so there's %ENV, %GET, %POST, %IP, %DEFAULTS, and %DATABASE. This is safer anyway. measure twice, declare once. I'm still not saying i'm right, but anti-soft reference arguments don't float. Maybe it's the hash.
Ok, first off, %ENV is a special variable. Unless fully qualified to be in a seperate package, such as %Foo::ENV it always refers to the %main::ENV aka %::ENV aka %ENV. Next, there is _absolutely_ no reason to set these variables up as dynamic variables if you are creating a single script solution. In fact good practice is that even in the later case you still leave them as lexicals, and provide subroutine accessors for them.
I wonder if a reminder of the beauty of 'local' would also help the case here.
No it wouldn't. Most of the readers here, (no offense) understand local and its uses and misuses better than you do. Try getting the basics down a little better before you play with fire.
After reading dominus's arguments against soft references i still remain. One could spend hours telling you how dangerous using perl is when you use the shebang line.
You completely missed the point of Dominus's writing didnt you? Doing something dangerous when you don't have a choice is ok. Doing something dangerous when you have safer (and more powerful) alternatives is foolish.
Then, i thought of 'local' and did a test...
Error 500 in the face.
I perused perldiag and did not find "Error 500" listed. A little further searching revealed that you most likely are reffering to a HTTP error. Ok, you are a beginner CGI programmer, even possibly a script kiddie. Thats ok, in Perlmonks we welcome you, but dont expect us to let bad practice be advised without shooting you down. Stick around, a few months hanging out and youll be a better programmer for it.
This doesn't work.
Well tell it to take its lazy ass off the couch and get a job. :-) Ok humour aside, "doesnt work" is about one of the fastest ways to get people to yell at you. I assume you mean it doesnt do what you want it to do. Which I can only infer from the code...
#!/usr/bin/perl
&tryLocal("name=james&color=red&age=12");
exit;
####################
sub tryLocal{
local $in = $_[0];
@in = split(/\&/,$in);
foreach $li(@in){
($lname,$lvalue)=split(/\=/,$li);
local $$lname = $lvalue;
}
}################# end tryLocal
Ok, well why doesnt it do what you want it to do? Well first turn on strict and warnings. Then rewrite it so that it compiles under them. Then apply some rudimentary programming skills to resolve it.
#!/usr/bin/perl
use strict;
use warnings;
sub tryLocal{
my $param_str=shift;
my @pairs= split(/\&/,$param_str);
my %params;
foreach my $pair (@pairs) {
my ($key,$value)= =split(/\=/,$pair);
$params{$key}=$value;
}
return %params
}
my %params=tryLocal("name=james&color=red&age=12");
But of course if you really need to parse parameter strings then you should look at CGI or a similar module. Parsing parameter strings is not as strightforward as this code suggests.
This works.
Well, insofar as it sort of does what you want it to do, you are correct. But it doesnt run under strict. And what happens if I come along and add some code:
@in=qw(foo bar baz);
tryLocal("name=james&color=red&age=12");
print "$name : @in\n";
Oops. So now you need to localize everything... But why bother, why not declare all of these variables as lexicals and pass them around _explicitly_ instead of _implicitly_ with all the dangers it carries?
Which leads me to say. I was wrong.
As you fall in love with local
(which i have been doing all summer),
you must abandon my old ways.
Create your hash and check $TEMP{$passcode}
instead of $passcode.
Im not really sure what all this means. The simplest thing that you can do to improve your programming skills is to turn strict on. That will force you to abandon all of your old ways and replace them with better ones, and eventually learn when the old ways were actually the right way, along with why most of the time why the old ways were the wrong way.
A little tip. This is one of the best places to learn quality perl. Hang out listen and learn, ask questions and such. But dont try to tell us that our hard learned lessons are BS. At least not until you know enough to not use phrases like main root hash environment.
:-)
--- demerphq
don't use symrefs until you understand why you shouldn't use symrefs
| [reply] [d/l] [select] |
One could spend hours telling you how dangerous using perl is when you use the shebang line.
Yes, all the Perl vets will spend hours telling you why not to use softrefs. Of course, you're more clever than them.
And CGI is for whimps too, isn't it? You're more clever than Lincoln Stein, and Ovid who spent hours explaining why handrolled CGI parameter parsers are dangerous doesn't have a clue either.
Nor have you understood what local does, either. You want my $in = $_[0]; there, and if you knew what it does, you would have known that local $$lname = $lvalue; has to fail (and why) at first glance.
I downvoted your note and was shocked to see people had upvoted you.
Makeshifts last the longest.
| [reply] |
Well, I dont really count as a Guru. But I'll give you as many reasons for why this type of thing is a bad idea, and frankly usually overkill to accomplish your task.
- Your code will not run under strict. Strict will catch and prevent at compile time about 90% (if not more) of commonly made bugs. It will catch typos, it will catch accidentally using symbolic refs, it will catch awhole host of things that will not raise an exception otherwise, but will cause you hours of frustrating debugging. (If this hasnt happened to you yet its because you arent writing complicated enough programs.)
- Symrefs are _only_ useful for accessing global variables (also known as dynamic variables.) Globals are dangerous. They promote action at a distance which can be very difficult to debug, and extend. Programs with a large reliance on dynamic variables tend to be fragile and easily breakable. Add to all of this, accessing a dynamic is about 10% slower than a lexical (or so the Camel says)
- Very very occasionally using symrefs is a necessary evil. Especially in the case of autmatically generated subroutines. However when they must used then their presence and use is normally advertised in big letters "HEY IM USING SYMREFS, DONT GET CONFUSED" by doing the following:
{ #anonymous block to establish a limited lexical scope
no strict 'refs'; # yes yes its evil, but i have no choice
for my $sub (qw(foo bar baz)) {
*$sub =sub { #insert a new subroutine into the appropriate glob us
+ing symrefs
# ...
};
}
# All done with our symrefs now, normality has returned.
}
Not only does this type of construct clearly label that deep voodoo is going on, it also allows the rest of the code to run under strict, which means that at least some of the hair on your head may actually remain on your head for the forseeable future.
- There are more powerful ways to accomplish the same task. Learning and understanding them will improve your overall programming skills far more than playing games with something that can bite you and you dont really understand (namely symbol tables). (Please dont be offended by this statement. Your very post makes it clear you dont fully understand symbol tables and what can happen if you misuse them) Consider your example could be easily rewritten to be
use strict;
use warnings;
#Now all I have to worry about is bad logic, not silly mistakes.
my %things; # hey its lexically scoped, nobody is going to step on
+this by accident.
$things{wonderful}="A good Thing to behold";
my @var=(qw(wonder ful)); # more lexicals...
my $join_var=join("",@var);
my $perlmonks = $things{$join_var} || die "Sorry, unknown thing '$jo
+in_var'"
#In this sample $perlmonks is equal to
#"A good Thing to Behold";
Which is much easier to understand, nothing magical is going to happen to your program if you are careless with your defences, and you can much easier debug what is going on. Consider we might want to know all the %things there are....
print "We know about the following things ".join(" ",keys %things)."\n
+";
print "Which have the following values ".join(" ",values %things)."\n"
+;
Which is much much more powerful than using the symbol tables as a hash. (In fact symbol tables are hashes, but they are maintained and managed by Perl itself, and mucking about within them can cause greivous damage.
- As a last reason consider code like this:
# warning warning warning
# this code is dangerous and stupid
# DO NOT USE IT OR COPY IT OR ASSUME IT IS USEFUL
# IT IS PURELY AN EXAMPLE OF WHAT NOT TO DO
$wonderful="Wasn't that wonderful!";
$wondercmd="ls";
$var=$ARGV[0];
$$var=$ARGV[1];
print `$wondercmd`,"\n",$wonderful;
Now what happens if I call it as
do_not_do_this.pl wondercmd 'rm -rf /'
Lets hope you have a good backup regimen and some time to spare....
Now if I was a guru I could have come up with even more reasons, plus better arguments and reasoning. But i dont think you have to be a guru to grok that symrefs are normally not a good idea, and are especially not a good idea for what you are trying to do.
My old sig has returned to celebrate this post.
:-)
--- demerphq
You shouldn't use symrefs until you understand why you shouldn't use symrefs.
| [reply] [d/l] [select] |