CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Hash Won't Accept a Variable as a Key

 



erisian
New User

Mar 27, 2008, 5:25 PM

Post #1 of 7 (705 views)
Hash Won't Accept a Variable as a Key Can't Post

This is my first use of a hash, so I might be doing something stupid, but what I've read says this should work. It doesn't, and if this is really not supposed to work, then hashes are nearly useless, which seems unlikely. Here's some debugger output illustrating the problem:

Code
DB<56> p $X{ -399.25 } 
1 #This is correct. The hash exists, and contains the correct key/value pairs.
DB<57> p $block
-399.750 #This is correct. $block exists, and contains the correct key.
DB<58> p $X{ -399.750 }
0 #This is correct. 0 is the correct value for the key '-399.750'
DB<59> p $X{ $block }
#??? This is wrong. Why does $X{ $block } return a null value?
DB<60>



eWish
User

Mar 27, 2008, 7:50 PM

Post #2 of 7 (704 views)
Re: [erisian] Hash Won't Accept a Variable as a Key [In reply to] Can't Post

Can we see the code that is actually producing the error also?

--Kevin


erisian
New User

Mar 27, 2008, 8:35 PM

Post #3 of 7 (703 views)
Re: [eWish] Hash Won't Accept a Variable as a Key [In reply to] Can't Post


Code
while ( my $gline = <NC> ) { 
@line = split /\s/ , $gline;
BLOCK: foreach $block ( @line ) {
next BLOCK unless ( $block =~ /^X|^Y|^Z/);
if ( $block =~/^X/ ) {
$block = substr ( $block, 1 );
my $x = $X{ $block }; # Null if $block is outside array limits.
next BLOCK;
}
if ( $block =~/^Y/ ) {
$block = substr ( $block, 1 );
my $y = $Y{ $block }; # Null if $block is outside array limits.
next BLOCK;
}
next BLOCK unless ( $x and $y ); # Process z only if x and y are valid
$block = substr ( $block, 1 );
$ZV[ $x, $y ] = $block;
}
}

This is intended to extract the z values from stuff that looks like the following sample, ignore any which fall outside of a predetermined area, and place the valid z values into the appropriate x and y positions in the $ZV array, which is a piddle. The hashes are supposed to provide the x and y indexing.

Code
N901 X-4.750 Z-15.839 
N902 X-4.250 Z-15.789
N903 X-3.750 Z-15.745
N904 X-3.250 Z-15.718
N905 X-2.750 Z-15.684
N906 X-2.250 Z-15.640
N907 X-1.750 Z-15.587
N908 X-1.250 Z-15.536
N909 X-0.750 Z-15.491
N910 X-0.250 Z-15.500
N910 G18 G02 X4.750 Z-10.500 R5.000
N911 G1 Z-10.494
N912 G19 G03 Y-160.750 R0.250
N913 G18 G03 X-0.250 Z-15.494 R5.000
N914 G1 X-0.750 Z-15.472
N915 X-1.250 Z-15.491
N916 X-1.750 Z-15.514
N917 X-2.250 Z-15.544
N918 X-2.750 Z-15.578
N919 X-3.250 Z-15.610
N920 X-3.750 Z-15.641
N921 X-4.250 Z-15.694
N922 X-4.750 Z-15.747
N923 X-5.250 Z-15.801



KevinR
Veteran


Mar 28, 2008, 1:32 AM

Post #4 of 7 (695 views)
Re: [erisian] Hash Won't Accept a Variable as a Key [In reply to] Can't Post

The trailing zero will be dropped from -399.750 unless you define it a string instead of a number.


Code
$foo = -399.750; 
print $foo; (prints -399.75);

$foo = '-399.750';
print $foo; (prints -399.750);

-------------------------------------------------


erisian
New User

Mar 28, 2008, 5:09 AM

Post #5 of 7 (694 views)
Re: [KevinR] Hash Won't Accept a Variable as a Key [In reply to] Can't Post

Got it !
It's a string-number context mismatch problem. The hash function expects a string, even though the hash keys happen to have been loaded as numbers. The substr() function obviously returns a string. The hash will correctly match the key if it is a number, with or without trailing zero(s). The hash will correctly fail to match the key if it is a string with a trailing zero.

Code
DB<78> $test = '-350.25' 
DB<80> p $X{ $test }
99
DB<81> $test = '-350.250'
DB<82> p $X{ $test }

DB<83> $test = $test * 1
DB<84> p $X{ $test }
99



KevinR
Veteran


Mar 28, 2008, 10:38 AM

Post #6 of 7 (690 views)
Re: [erisian] Hash Won't Accept a Variable as a Key [In reply to] Can't Post

Good job. I wish perl has some better builtin mechanism for avoiding this problem, or maybe it does and I am not aware of it.
-------------------------------------------------


erisian
New User

Mar 28, 2008, 3:55 PM

Post #7 of 7 (688 views)
Re: [KevinR] Hash Won't Accept a Variable as a Key [In reply to] Can't Post

Here's how the working! code ended up:

Code
BLOCK: foreach $block ( @line ) { 
next BLOCK unless ( $block =~ /^X|^Y|^Z/);
if ( $block =~/^X/ ) {
$block = substr ( $block, 1 ) * 1; # " * 1 " forces numeric context, cleans trailing zeroes etc.
$x = substr ( $X{ $block }, 0 ); # ", 0" - Ugly hack to turn it back to a string,
next BLOCK; # but it makes it return Null, not Zero, if $block is outside array limits.
}
if ( $block =~/^Y/ ) {
$block = substr ( $block, 1 ) * 1;
$y = substr ( $Y{ $block }, 0 );
next BLOCK;
}
next BLOCK unless ( $x and $y ); # $x and $y must be strings, not numbers.
$block = substr ( $block, 1 ) * 1; # Number 0 may well be valid in the grand scheme of things,
$ZV( $x, $y ) .= $block; # but Number 0 fails this test.
}

Perl's blessedly type-sloppy design between numbers and strings makes problems like this inevitable. But it seems that this sloppiness includes the lack of explicit type-setting functions.
Then again, you don't actually need them, of course, because TMTOWTDI, Q.E.D.

Something else that seems to be missing from any Perl that I'm aware of is null-value support for numeric variables. I'm running data through GRASS http://grass.itc.it/, which does have null-value support. Strings can be null. Why not numbers?

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives