Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
02-12-2006, 05:40 PM
|
#1
|
Senior Member
Registered: May 2004
Location: Hilliard, Ohio, USA
Distribution: Slackware, Kubuntu
Posts: 1,851
Rep:
|
Using hash value as key for other hash in Perl
I'm having a fit with this. I have the following hashes set up:
Code:
my %fleet_def = ( # defenders fleet
"sc" => Ship -> new(),
"lc" => Ship -> new(),
"lf" => Ship -> new(),
"hf" => Ship -> new(),
"cr" => Ship -> new(),
"bs" => Ship -> new(),
"cs" => Ship -> new(),
"rc" => Ship -> new(),
"ep" => Ship -> new(),
"bm" => Ship -> new(),
"ss" => Ship -> new(),
"de" => Ship -> new(),
"rip" => Ship -> new(),
"ml" => Ship -> new(),
"sl" => Ship -> new(),
"hl" => Ship -> new(),
"gc" => Ship -> new(),
"ic" => Ship -> new(),
"pc" => Ship -> new(),
"ssd" => Ship -> new(),
"lsd" => Ship -> new(),
);
my %rand_hash = ( # hash for random number gen. to determine ship
"1" => "sc",
"2" => "lc",
"3" => "lf",
"4" => "hf",
"5" => "cr",
"6" => "bs",
"7" => "cs",
"8" => "rc",
"9" => "ep",
"10" => "bm",
"11" => "ss",
"12" => "de",
"13" => "rip",
"14" => "ml",
"15" => "sl",
"16" => "hl",
"17" => "gc",
"18" => "ic",
"19" => "pc",
"20" => "ssd",
"21" => "lsd",
);
What I want to do using these, is call a random number, and use it to call a variable in the Ship struct that is set up, like this:
Code:
$rand = ( int(rand(13)) + 1 );
until ( defined( $fleet_att{$rand_hash{$rand}} -> quantity ) { #test if ship exists
$rand = ( int(rand(13)) + 1 ); #if not, reinitialize the variable with a new rand
}
But, for some reason, every time I execute this, I get these errors:
Code:
[scuzzy@slackdell /home/scuzzy/ogame/perlsim/PerlSim]$ ./PerlSim.pl
syntax error at ./PerlSim.pl line 464, near ") {"
syntax error at ./PerlSim.pl line 470, near ") {"
syntax error at ./PerlSim.pl line 475, near "}"
Execution of ./PerlSim.pl aborted due to compilation errors.
[scuzzy@slackdell /home/scuzzy/ogame/perlsim/PerlSim]$
And yes, I'm doing this multiple times (hence the similar errors). What I don't understand, is that ") {" never appears in the code, so I can't isolate the problem, and I have trouble believing Perl cannot do this. Just in case it's needed, here is the entire section of code in which these are used:
Code:
foreach $ship ( keys %fleet_def ) {
$rand = ( int(rand(13)) + 1 );
until ( defined($fleet_att{$rand_hash{$rand}} -> quantity) { #test if ship exists
$rand = ( int(rand(13)) + 1 ); #if not, reinitialize the variable with a new rand
}
&shoot($ship, $rand_hash{$rand}, 2); # call &shoot function
while ( &rf($ship, $rand) ) { # call &rf function to see if ship shoots again
$rand = ( int(rand(13)) + 1 );
until ( defined( $fleet_att{$rand_hash{$rand}} -> quantity ) { #test if ship exists
$rand = ( int(rand(13)) + 1 ); #if not, reinitialize the variable with a new rand
}
&shoot($ship, $rand_hash{$rand}, 2); # call &shoot function
}
}
|
|
|
02-12-2006, 11:34 PM
|
#2
|
LQ Guru
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,415
|
Actually, the 1st line of your last quoted code block is:
foreach $ship ( keys %fleet_def ) {
which includes ") {" as per the error msg you are getting ...
Hopefully you are using:
#!/usr/bin/perl -w
and
use strict;
at the top of your code ?
|
|
|
02-13-2006, 12:16 PM
|
#3
|
Senior Member
Registered: May 2004
Location: Hilliard, Ohio, USA
Distribution: Slackware, Kubuntu
Posts: 1,851
Original Poster
Rep:
|
OK - I got that problem solved - missed a parentheses
But I have other problems now. When I go to execute it, I get these errors:
Code:
[scuzzy@slackdell /home/scuzzy/ogame/perlsim/PerlSim]$ ./PerlSim.pl
Global symbol "$hull" requires explicit package name at ./PerlSim.pl line 139.
Global symbol "$weapon" requires explicit package name at ./PerlSim.pl line 140.
Global symbol "$shield" requires explicit package name at ./PerlSim.pl line 140.
Global symbol "$hull" requires explicit package name at ./PerlSim.pl line 141.
Global symbol "$weapon" requires explicit package name at ./PerlSim.pl line 141.
Global symbol "$shield" requires explicit package name at ./PerlSim.pl line 141.
Global symbol "$shield" requires explicit package name at ./PerlSim.pl line 146.
Global symbol "$shield" requires explicit package name at ./PerlSim.pl line 146.
Global symbol "$weapon" requires explicit package name at ./PerlSim.pl line 146.
Global symbol "$target" requires explicit package name at ./PerlSim.pl line 147.
Global symbol "$shield" requires explicit package name at ./PerlSim.pl line 147.
Global symbol "$target" requires explicit package name at ./PerlSim.pl line 148.
Global symbol "$shield" requires explicit package name at ./PerlSim.pl line 148.
Global symbol "$hull" requires explicit package name at ./PerlSim.pl line 150.
Global symbol "$hull" requires explicit package name at ./PerlSim.pl line 151.
Global symbol "$target" requires explicit package name at ./PerlSim.pl line 157.
Global symbol "$target" requires explicit package name at ./PerlSim.pl line 158.
Global symbol "$shield" requires explicit package name at ./PerlSim.pl line 158.
Global symbol "$target" requires explicit package name at ./PerlSim.pl line 159.
Global symbol "$target" requires explicit package name at ./PerlSim.pl line 160.
Global symbol "$shield" requires explicit package name at ./PerlSim.pl line 160.
Global symbol "$target" requires explicit package name at ./PerlSim.pl line 164.
Global symbol "$target" requires explicit package name at ./PerlSim.pl line 165.
Global symbol "$shield" requires explicit package name at ./PerlSim.pl line 165.
Global symbol "$target" requires explicit package name at ./PerlSim.pl line 166.
Global symbol "$target" requires explicit package name at ./PerlSim.pl line 167.
Global symbol "$shield" requires explicit package name at ./PerlSim.pl line 167.
Global symbol "%rf_hash" requires explicit package name at ./PerlSim.pl line 221.
Global symbol "%rf_hash" requires explicit package name at ./PerlSim.pl line 222.
Global symbol "$desc" requires explicit package name at ./PerlSim.pl line 446.
Global symbol "$desc" requires explicit package name at ./PerlSim.pl line 449.
Global symbol "$desc" requires explicit package name at ./PerlSim.pl line 450.
Global symbol "$desc" requires explicit package name at ./PerlSim.pl line 451.
Global symbol "$desc" requires explicit package name at ./PerlSim.pl line 452.
Global symbol "$desc" requires explicit package name at ./PerlSim.pl line 453.
Global symbol "$desc" requires explicit package name at ./PerlSim.pl line 454.
Global symbol "$desc" requires explicit package name at ./PerlSim.pl line 455.
Execution of ./PerlSim.pl aborted due to compilation errors.
[scuzzy@slackdell /home/scuzzy/ogame/perlsim/PerlSim]$
I think this might be a problem with the scoping, but there has to be a more elegant way of fixing that then explicitly saying $main:: on every variable. That said, the current code is here: http://www.scuzzman.org/perl/PerlSim.pl
Edit: I just made all the variables global, and now that's not happening... I shouldn't do this though, should I? http://www.scuzzman.org/perl/PerlSimv2.pl
Last edited by scuzzman; 02-13-2006 at 12:39 PM.
|
|
|
02-13-2006, 05:54 PM
|
#4
|
LQ Guru
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,415
|
A few pts; feel free to ignore ...
1. Perl is not shell ie you do not have to pre-declare all your fns before you use them. Try the C method ie after any global declarations (see below), start with a main or ctrl fn and physically put the other subs below that. Perl is sort-of compiled before it's run.
2. Try to only declare variables as 'my' within the sub they are used. Pass as params where needed.
My guideline is that if you need a var in a lot of subs, declare a 'global' pkg and put them in there eg:
<code>
# Declare Config pkg so we can refer to it anywhere
{
package cfg;
# Config file params
%cfg: arams = ();
# Database handle
$cfg::dbh = '';
}
</code>
3. Put a proper header for each sub, so you and/or anyone else can work out what's happening. here's an example of the way I do it:
<code>
#******************************************************************************
#
# Function : process_cc_rows
#
# Description : Main ctrl sub to delete cc rows older than eg 6 mths.
#
# Params : none
#
# Returns : none
#
#******************************************************************************
sub process_cc_rows
{
my (
$error_msg # log/email error if any
);
# Create a txn wrapper in case we have to rollback
db_start_txn();
# Delete all rows older than cfg specified
db_delete_cc_rows();
}
</code>
4. Personally, rather than require the user to re-enter all params each time, I'd create a (plain text) config or data file they can edit, so they can only change the values they want to (& change their minds easily).
Then just read the file at startup.
5. As you say, try not to use (unqualified) globals & try to minimise the num that you do you use. How different subs a var is used in constitute justification for putting a var into a global pkg is a personal judgement call. ;-)
6. No need to prefix subs with '&' when calling them. (unless passing as a ref ie \&sub_name). That's old-school Perl v4.
HTH
|
|
|
02-13-2006, 05:56 PM
|
#5
|
LQ Guru
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,415
|
PS : Note to moderators: why can't I edit my post??? I am logged in ...
|
|
|
02-14-2006, 05:51 AM
|
#6
|
Senior Member
Registered: May 2004
Location: Hilliard, Ohio, USA
Distribution: Slackware, Kubuntu
Posts: 1,851
Original Poster
Rep:
|
Thanks for the pointers - my little project is starting to come together now
I have yet to implement your suggestions (though, I likely will). I'm waiting until I at least get it to work right once... then, I'm going to worry about pretty code vs. functional code. One thing though, it is VERY slow - would making the variables local speed it up?
|
|
|
02-14-2006, 06:08 PM
|
#7
|
LQ Guru
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,415
|
No, speed is generally due to bad design at some level eg unnecessary loops, wrong algorithms or badly written algorithms.
As for 'pretty' vs 'working', as someone whose been doing this for xxxxx yrs, take it from me, if you don't make it look right as you go, you'll never have time/inclination to go back and correct it later, esp in commercial env.
Also, it makes it easier to debug as you go.
|
|
|
All times are GMT -5. The time now is 08:12 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|