Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Re: Re: Finding missing elements in a sequence (code)

by danger (Priest)
on Nov 06, 2001 at 22:49 UTC ( [id://123652]=note: print w/replies, xml ) Need Help??


in reply to Re: Finding missing elements in a sequence (code)
in thread Finding missing elements in a sequence (code)

Here's a slightly more in-depth analysis of the problem in the subroutine (for those that may be interested):

We already know Perl can use a string that looks like a number as a number. Each SV (perl's internal representation of scalar value) has various slots to hold different kinds of data (and various flags to indicate which slots are currently valid) --- we will just simplify this to two slots, one for Strings and one for Numbers, for this discussion ...

Now, if we have $a = '0001' that string is stored in the String slot and a flag is set to indicate that value the String slot is OK to use. Once we use this variable as a number (but not assigning anything new to it) as in: $b = $a + 0;, perl creates the numeric equivalent of '0001', which is just 1, stores it in the Number slot of $a and sets another flag to indicate it is OK to use the Number slot too. At this point both flags are set and in string context we'll get '0001' and in numeric context we'll get 1.

Now, in deprecated's routine, the list of 0-padded strings is sorted numerically ... which is a numeric context and thus puts the numeric value of each array element into that element's Number slot and sets the flag for that slot. Thus each SV in your array now has both String and Number slots filled and listed as OK. Next you grab the $low and $high elements from the array (these are copies of the same SV's so they have both slots filled and flagged as OK too). Now, the range op (..) works on either strings or numbers, but will assume numeric context if the Number flags are present (even if the String flags are also set). So when you loop over $low .. $high to make keys for your hash, you are getting 1 .. 9 instead of '0001' .. '0009', and those numbers are then stringified as hash keys so you have $isthere{'1'} instead of $isthere{'0001'}.

At this point your hash is populated with numbers as keys (ie, keys are the strings: '1', '2' ...). Next you loop over @list to use each element as a key in the same hash and set it's value to "yes" (a true value). However, hash keys are string context, so the String value of each element is used in this case and you are actually *adding* new keys to the hash, of the form '0001', '0002', etc. (in other words, you have more keys in the hash than you think at this point). Later when you grep back all the keys that aren't true you get all of the keys that look like '1', '2' (because none of them were ever set to true), and filter out all of the '0001', '0002' keys (because they are set to true values).

That leads to two possible solutions: don't sort the list passed to the sub numerically (if everything is 0-padded, string-wise sorting will be correct); Or, use clemburg's trick to numify the array elements when you use them to set true values in the hash.

Here is a snippet of code to demonstrate all this behaviour:

my $lo = '0007'; my $hi = '0014'; print "$lo:$hi:",join ' ', $lo .. $hi, "\n"; # now set numeric values and flags by using $lo and $hi # in numeric context: my $num = $lo + $hi; print "$lo:$hi:",join ' ', $lo .. $hi, "\n"; __END__ Output: 0007:0014:0007 0008 0009 0010 0011 0012 0013 0014 0007:0014:7 8 9 10 11 12 13 14

We can see that: a) a range over strings that look like numbers does what we want (no need to worry about that clemburg), and b) after the number flags are set, the range op assumes numeric context and uses the numeric values (but the string values are still valid too as printing the variables directly indicates).

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://123652]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-03-19 02:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found