(jcwren) Re: calling a sub from an if statement
by jcwren (Prior) on Jul 23, 2000 at 23:17 UTC
|
Two things: Do you really know that your if statement is succeeding? When you have doubts about things like that, putting a print, die(), or some other statement that removes the question of whether your subroutine is actually getting called is needed.
The second thing is the ampersand really isn't needed in the context that you're calling msg(). Typically, when you're passing arguments to a subroutine, the ampersand is not used. It's used when you want to pass the current value of @_ to the subroutine.
I ran your code, setting $proto = "HTTP/1.0", and then to "xHTTP/1.0". In both cases, it ran fine. This leads me to believe that the value that you think should be in $proto is not what you expect. To test your theory, put a print or die() statement after the if that will display the value of $proto.
--Chris
e-mail jcwren | [reply] |
Re: calling a sub from an if statement
by steveAZ98 (Monk) on Jul 23, 2000 at 23:37 UTC
|
I believe that your msgs hash may be out of scope when you call msg. I tried your code and ran into the same problems. I rewrote it like this
my $msgs = { '200' => 'OK',
'400' => 'Bad Request',
'403' => 'Forbidden',
'404' => 'Not Found',
'500' => 'Internal Sever Error',
};
sub msg {
print "HTTP/1.0 $_[0] $msgs->{$_[0]}\n";
}
if (1 == 1) {
msg(400);
}
And it seems to work fine.
On a side note you don't need double quotes around your hash vars, as they're not interpolated. Just something I learned and thought I'd pass on. It is supposedly a performance hit, although I've never tested it myself.
| [reply] [d/l] |
|
|
Steve, you're code is definitely cleaner to look at, but I'm curious what problems you had running it the original. I copied it verbatim from the HTML, deleted the non-code, and ran it. I got two messages, one from the lone &msg(400), the other from the true if(), since $proto is undefined (no use strict and no -w. *gasp*).
I then defined $proto with "HTTP/1.0", and got only one message, since the if() failed.
What problems were you running into?
--Chris
e-mail jcwren
| [reply] |
Re: calling a sub from an if statement
by le (Friar) on Jul 24, 2000 at 00:01 UTC
|
I just wanted to say that
sub msg {
$msg_num = @_[0];
# ...
is not necessarily what you want.
@_[0] # An array slice
$_[0] # The first element of the array @_ (usually passed to the subro
+utine)
| [reply] [d/l] [select] |
(jcwren) Re: calling a sub from an if statement
by jcwren (Prior) on Jul 24, 2000 at 00:07 UTC
|
tye is correct, however, his solution leaves a touch to be desired. Simply move the %msgs has to the top of the file. And I would recommend taking SteveAZ98's method of initializing the hash. Using => is a lot cleaner than the comma separated key/value pairs. Much more obvious which messages goes with which key, particularly if you decide to add to the list.
You could also simplify in a few places. Where you have
if ($method ne "GET") {
if ($method ne "POST") {
msg(400);
}
}
use instead
if ($method ne "GET" && $method ne "POST")
{
msg(400);
}
Note that you probably want a return or and exit at this point, otherwise, you're going to continue executing code, after you've kicked an error message out. This is usually not what you want to do.
You can also simplify your file reading with this:
open(FILE1, $ARGV[0]);
@lines = <FILE1>;
And, of course, as a responsible programmer, you'll be wanting to close the file when you're done with it. <G>
--Chris
e-mail jcwren | [reply] [d/l] [select] |
|
|
I don't know what you don't like about using BEGIN, perhaps you could elaborate. As for moving %msg to the top of the file, I specifically avoided that route because there are several problems with it. First, it can be hard to maintain. One little pass through moving things around to try to clean up your code and suddenly you've got a call to the sub before the data is initialized again.
Second, I consider it a bad habit since when you get into more advanced coding, it isn't sufficient. For example, if this becomes a module:
package My::Module;
# Keep this next line at the very top, please:
%msgs= (400=>"Bad Request",...);
[...]
use My::OtherModule;
[...]
sub msg {
die "HTTP/1.0 $_[0] $msgs{$_[0]}\n";
}
Then all we need is:
package My::OtherModule;
[...]
sub import {
msg(400) if ! $valid;
[....]
}
and we run back into the same problem. | [reply] [d/l] [select] |
Re: calling a sub from an if statement
by tye (Sage) on Jul 23, 2000 at 23:58 UTC
|
It isn't that %msgs is out of scope (that would generate an error). It is that sub msg is being called the first time before %msgs has been initialized.
You could fix that with:
my %msgs;
BEGIN { %msgs= (400=>"Bad Request",...); }
| [reply] [d/l] [select] |
Re: calling a sub from an if statement
by cburns (Novice) on Jul 23, 2000 at 23:51 UTC
|
Tried you suggestions, to no avail. Here's all the code, incase something else is causing the problem: #!/usr/local/bin/perl
# this is the code for sever.pl, my mini-server
my @lines;
open(FILE1, $ARGV[0]);
while (<FILE1>) {
push(@lines, $_);
}
($method, $url, $proto) = split(/ /, $lines[0]);
if ($method ne "GET") {
if ($method ne "POST") {
msg(400);
}
}
if ($proto ne "HTTP/1.0") {
msg(400); #here's where sub msg doesn't work
}
if ($method eq "POST") {
open(FILE2, $ARGV[1]);
while (<FILE2>) {
$ENV{'REQUEST_QUERYSTRING'} = $_;
}
print "the querystring is: $ENV{'REQUEST_QUERYSTRING'}\n";
@q_string = split (/&/, $ENV{'REQUEST_QUERYSTRING'});
foreach $pair (@q_string) {
my @temp = split (/=/, $pair);
$param{$temp[0]} = $temp[1];
print "$temp[0] = $param{$temp[0]}\n";
}
}
%msgs = ("200", "OK", "400", "Bad Request", "403", "Forbidden", "404",
+ "Not Found", "500", "Internal Server Error");
msg(400); #here's where sub msg works
sub msg {
$msg_num = @_[0];
$msg_txt = "$msg_num $msgs{$msg_num}";
print "HTTP/1.0 $msg_txt\n";
}
and here's the file I'm passing to server.pl:
> more badreq.txt
GET /index.html HTTP/1.1
and here's my output:
> ./server.pl badreq2.txt
HTTP/1.0 400
HTTP/1.0 400 Bad Request
What do you think?
Thanks! | [reply] [d/l] [select] |
|
|
Ahh.. the problem is that your hash isn't defined yet when you call msg in the if statement, but it is defined when you call it later on in the program. %msgs has to be defined before any calls to msg()
| [reply] |
Re: calling a sub from an if statement
by qi3ber (Scribe) on Jul 25, 2000 at 21:32 UTC
|
Another alternative would be to move the hash definition
into the function definition, since that is the only place
where that is used. This satisfies both the desire to
modularize your code, and the need to the have the hash
defined everwhere that the msg function is called. In this
case the definition for your msg subroutine would be:
sub msg {
my $msgs = { '200' => 'OK',
'400' => 'Bad Request',
'403' => 'Forbidden',
'404' => 'Not Found',
'500' => 'Internal Sever Error',
};
my $msg_num = $_[0];
my $msg_txt = "$msg_num $msgs{$msg_num}";
print "HTTP/1.0 $msg_txt\n";
}
| [reply] [d/l] |
Re: calling a sub from an if statement
by cburns (Novice) on Jul 23, 2000 at 23:53 UTC
|
oops, didn't refresh to see the second response before my last post.
let me give that a try... | [reply] |