Re: Re: Re: Re: Many strings make one variable?
by demerphq (Chancellor) on Oct 15, 2002 at 10:40 UTC
|
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] |
|
|
2 follow-up question if you're up for it:
1.) i turned on strict and was amazed at
all the crap i was doing wrong!
I also tried to incude the library 'warnings'
which failed (my perl is 5.005), is the
shebang -w switch a suitable substitute
for use warnings lib?
Will
#!/usr/bin/perl -w
work in place of
use warnings;
2.) Do you see anything fundamentally flawed with my
use of 'my' instead of local? The strict and -w switch
stopped outputing bad news to my error logs, so am i
okay now? Or is there something else i don't know about
to keep me on the right path to using perl correctly.
#!/usr/bin/perl -w
# this script outputs a gif
# set color, width, and height
use strict;
&printGIF("FF0000","33","10");
######################################
sub printGIF{
my $color = $_[0];
my $WH = sprintf("%lX",$_[1]);
my $HH = sprintf("%lX",$_[2]);
$color =~ s/(..)(..)(..)/$1\|$2\|$3/;
my($RH,$GH,$BH)=split(/\|/,$color);
print STDOUT "Content-type:image/gif\n\n";
my @gif=(
"47", "49", "46", "38", "37", "61", "$WH", "00",
"$HH", "00", "A1", "01", "00", "$RH", "$GH", "$BH",
"FF", "FF", "FF", "00", "00", "00", "00", "00",
"00", "21", "F9", "04", "05", "00", "00", "01",
"00", "2C", "00", "00", "00", "00", "$WH", "00",
"$HH", "00", "40", "02", "$HH", "84", "8F", "A9",
"CB", "ED", "0F", "A3", "9C", "B4", "DA", "8B",
"B3", "DE", "9C", "17", "00", "3B"
);
binmode (STDOUT); # if needed
foreach my $bit(@gif){
my $bita = hex($bit);
$bita = pack("C",$bita);
print STDOUT $bita;
}
}#################################### end printGIF
When i say correct use of perl i mean a clean running program which could open and close millions of times with no overflow problems.
jtrue
| [reply] [d/l] [select] |
|
|
Yes, the -w switch is acceptable - there was in fact no warnings pragma before Perl 5.6, so it's a fairly recent thing. I still prefer -w for the time being as I never need to switch off warnings anywhere, anyway. (The warnings pragma allows for a more finegrained control if you do: you don't have to switch warnings off entirely anymore, you can selectively disable only specific ones.)
The script is fine, "clean" wise, but could be written quite a lot more succintly. The only technical mistake is writing "$WH" etc where $WH (without the quotes) would do. If you're only using a single variable, you almost never want to put it in quotes. (There are a rare few cases, but you'll know those when you see them.)
One thing I strongly urge you to, though, is to properly indent your code. It is barely acceptable in that short script, but would make a more complex one completely unreadable.
Another note is that you're outputting a CGI header in your printGIF routine: if you go to the trouble of writing a function, then make it do exactly one thing. In this case, generate a GIF file. Nothing else. The header, in this case, is the main program's job. That way, you get functions you can reuse in other scripts later. For the same reason I would have the function return the GIF file, rather than printing it to STDOUT directly.
Which brings up another point you might want to know about: the $|++; I dumped in there. See Suffering from Buffering about it.
Here's how I'd write that:
#!/usr/bin/perl -w
# this script outputs a gif
# set color, width, and height
use strict;
$|++;
binmode STDOUT;
print "Content-Type: image/gif\n\n";
print gif_file "FF0000", 0x33, 0x10;
######################################
sub gif_file{
my ($hexrgb, $wid, $hgh) = @_;
my %c;
@c{qw(r g b)} = map hex, unpack "A2"x3, $hexrgb;
return pack "C*", (
0x47, 0x49, 0x46, 0x38, 0x37, 0x61, $wid, 0x00,
$hgh, 0x00, 0xA1, 0x01, 0x00, $c{r}, $c{g}, $c{b},
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x21, 0xF9, 0x04, 0x05, 0x00, 0x00, 0x01,
0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, $wid, 0x00,
$hgh, 0x00, 0x40, 0x02, $hgh, 0x84, 0x8F, 0xA9,
0xCB, 0xED, 0x0F, 0xA3, 0x9C, 0xB4, 0xDA, 0x8B,
0xB3, 0xDE, 0x9C, 0x17, 0x00, 0x3B,
);
}
I would normally have used $width and $height instead of the shorter forms, but wanted to keep the hexdump aligned and somewhat compact.
Makeshifts last the longest. | [reply] [d/l] |
|
|
|
|
|
|
|
|
|
|
Will -w work in place of use warnings;
Yes. But use warnings is more powerful and localized to the module it is used in. If/when you upgrade to 5.6 or later then try to get into the habit of using warnings and not -w.
As for the code, it looks ok to me. (In principle.) Although I might write
my $bita=pack("C,hex($bit));
instead. And
my($RH,$GH,$BH)=($color =~ /(..)(..)(..)/);
Also it would be a good idea to get into the habit of indenting properly. You can check out the tool "PerlTidy" hosted on source forge to do have it done automatically for you. perlstyle will have some hints for you with regard to programming style. For instance $RH is not the best var name. To me it implies a filehandle or something else with "mystic" overtones (due to its captialization). I would probably have just used $red instead...
Ultimately it looks like you are on the right path... Keep it up!
HTH
--- demerphq
my friends call me, usually because I'm late....
| [reply] [d/l] [select] |
|
|
|
|
Re^4: Many strings make one variable?
by Aristotle (Chancellor) on Oct 15, 2002 at 08:50 UTC
|
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] |
|
|
my $in = $_[0];
has nothing to do with the original test i did.
the local test came in with the line "local $lname" vs $lname.
Just had a nice read on 'my'
pretty cool but 'local' works to.
see original question: 205160
I also just read local is better than 'my' for file handles
perlman:perlsub
NOTE: In general, you should be using ``my'' instead of ``local'', bec
+ause it's faster and safer. Exceptions to this include the global pun
+ctuation variables, filehandles and formats, and direct manipulation
+of the Perl symbol table itself. Format variables often use ``local''
+ though, as do other variables whose current value must be visible to
+ called subroutines.
| [reply] [d/l] [select] |
|
|
No, it doesn't have anything to do with it, nor does the fact that you're parsing CGI parameters on your own. But what peeved me is how you dismissed Dominus' arguments off hand and then you followed up with a bunch of typical ignorant mistakes, when it was obvious you didn't even understand what local does. local seems to work where my should be used because it does what seems to have the same effect, even though it's completely different from what you want.
Sorry for flying off the handle that badly, but you appeared quite unwilling to learn, and it seems you're not after all. Maybe you just "learned" Perl from reading other people's scripts? That frequently teaches awful habits because a lot of the freely available Perl code out there is really awful. If you want to continue that approach, I suggest you check out the NMS archive. Those scripts where expressly written to be an example of good code. merlyn's many various columns also contain well written (if sometimes a bit condensed) code.
I really suggest you get a good book, though. The O'Reilly Llama book is a manageable size and a decent intro, although you'll probably want to skip the chapter or two at this point. The rest of their Perl books are also good; the Camel book is the "standard" reference on Perl, but has grown to a pretty hefty size in its 3rd edition. The Book Reviews section here on this site may also be helpful.
Makeshifts last the longest.
| [reply] |
|
|
|
|
I also just read local is better than 'my' for file handles
Yes this is true for advanced scenarios. However using anonymous filehandles available in 5.6 and later (or is it earlier as well?) avoids almost all of the scenarios where localising a filehandle is necessary. (Well, an exception being when dealing with older code that still uses dynamic filehandles instead of anonymous ones)
open my $private_filehandle,"<",$0 or die "Weird! failed to open mysel
+f ($0) : $!";
Local is only really needed when localizing special filehandles like STDOUT and the like, or when localizing special variables like @ARGV and $_ and %ENV or whatever. (Actually this is not strictly true, sometimes using dynamic scoping is a powerful way to configure a module, for instance Data::Dumper, but of course that was written by a real guru, and the justifications are beyond the scope of your skills and this reply.) The note you post is most likely from an earlier version of perl, or hasnt been updated since an earlier version of perl.
--- demerphq
my friends call me, usually because I'm late....
| [reply] [d/l] |