Markdown Format | JSON API | MCP Server Tool
Found in /usr/share/perl/5.34/pod/perlfaq3.pod How can I free an array or hash so my program shrinks? (contributed by Michael Carman) You usually can't. Memory allocated to lexicals (i.e. my() variables) cannot be reclaimed or reused even if they go out of scope. It is reserved in case the variables come back into scope. Memory allocated to global variables can be reused (within your program) by using undef() and/or delete(). On most operating systems, memory allocated to a program can never be returned to the system. That's why long-running programs sometimes re- exec themselves. Some operating systems (notably, systems that use mmap(2) for allocating large chunks of memory) can reclaim memory that is no longer used, but on such systems, perl must be configured and compiled to use the OS's malloc, not perl's. In general, memory allocation and de-allocation isn't something you can or should be worrying about much in Perl. See also "How can I make my Perl program take less memory?" Found in /usr/share/perl/5.34/pod/perlfaq4.pod How do I test whether two arrays or hashes are equal? The following code works for single-level arrays. It uses a stringwise comparison, and does not distinguish defined versus undefined empty strings. Modify if you have other needs. $are_equal = compare_arrays(\@frogs, \@toads); sub compare_arrays { my ($first, $second) = @_; no warnings; # silence spurious -w undef complaints return 0 unless @$first == @$second; for (my $i = 0; $i < @$first; $i++) { return 0 if $first->[$i] ne $second->[$i]; } return 1; } For multilevel structures, you may wish to use an approach more like this one. It uses the CPAN module FreezeThaw: use FreezeThaw qw(cmpStr); my @a = my @b = ( "this", "that", [ "more", "stuff" ] ); printf "a and b contain %s arrays\n", cmpStr(\@a, \@b) == 0 ? "the same" : "different"; This approach also works for comparing hashes. Here we'll demonstrate two different answers: use FreezeThaw qw(cmpStr cmpStrHard); my %a = my %b = ( "this" => "that", "extra" => [ "more", "stuff" ] ); $a{EXTRA} = \%b; $b{EXTRA} = \%a; printf "a and b contain %s hashes\n", cmpStr(\%a, \%b) == 0 ? "the same" : "different"; printf "a and b contain %s hashes\n", cmpStrHard(\%a, \%b) == 0 ? "the same" : "different"; The first reports that both those the hashes contain the same data, while the second reports that they do not. Which you prefer is left as an exercise to the reader. Why does defined() return true on empty arrays and hashes? The short story is that you should probably only use defined on scalars or functions, not on aggregates (arrays and hashes). See "defined" in perlfunc in the 5.004 release or later of Perl for more detail. How do I process an entire hash? (contributed by brian d foy) There are a couple of ways that you can process an entire hash. You can get a list of keys, then go through each key, or grab a one key-value pair at a time. To go through all of the keys, use the "keys" function. This extracts all of the keys of the hash and gives them back to you as a list. You can then get the value through the particular key you're processing: foreach my $key ( keys %hash ) { my $value = $hash{$key} ... } Once you have the list of keys, you can process that list before you process the hash elements. For instance, you can sort the keys so you can process them in lexical order: foreach my $key ( sort keys %hash ) { my $value = $hash{$key} ... } Or, you might want to only process some of the items. If you only want to deal with the keys that start with "text:", you can select just those using "grep": foreach my $key ( grep /^text:/, keys %hash ) { my $value = $hash{$key} ... } If the hash is very large, you might not want to create a long list of keys. To save some memory, you can grab one key-value pair at a time using "each()", which returns a pair you haven't seen yet: while( my( $key, $value ) = each( %hash ) ) { ... } The "each" operator returns the pairs in apparently random order, so if ordering matters to you, you'll have to stick with the "keys" method. The "each()" operator can be a bit tricky though. You can't add or delete keys of the hash while you're using it without possibly skipping or re-processing some pairs after Perl internally rehashes all of the elements. Additionally, a hash has only one iterator, so if you mix "keys", "values", or "each" on the same hash, you risk resetting the iterator and messing up your processing. See the "each" entry in perlfunc for more details. How do I merge two hashes? (contributed by brian d foy) Before you decide to merge two hashes, you have to decide what to do if both hashes contain keys that are the same and if you want to leave the original hashes as they were. If you want to preserve the original hashes, copy one hash (%hash1) to a new hash (%new_hash), then add the keys from the other hash (%hash2 to the new hash. Checking that the key already exists in %new_hash gives you a chance to decide what to do with the duplicates: my %new_hash = %hash1; # make a copy; leave %hash1 alone foreach my $key2 ( keys %hash2 ) { if( exists $new_hash{$key2} ) { warn "Key [$key2] is in both hashes!"; # handle the duplicate (perhaps only warning) ... next; } else { $new_hash{$key2} = $hash2{$key2}; } } If you don't want to create a new hash, you can still use this looping technique; just change the %new_hash to %hash1. foreach my $key2 ( keys %hash2 ) { if( exists $hash1{$key2} ) { warn "Key [$key2] is in both hashes!"; # handle the duplicate (perhaps only warning) ... next; } else { $hash1{$key2} = $hash2{$key2}; } } If you don't care that one hash overwrites keys and values from the other, you could just use a hash slice to add one hash to another. In this case, values from %hash2 replace values from %hash1 when they have keys in common: @hash1{ keys %hash2 } = values %hash2; What happens if I add or remove keys from a hash while iterating over it? (contributed by brian d foy) The easy answer is "Don't do that!" If you iterate through the hash with each(), you can delete the key most recently returned without worrying about it. If you delete or add other keys, the iterator may skip or double up on them since perl may rearrange the hash table. See the entry for "each()" in perlfunc. How do I look up a hash element by value? Create a reverse hash: my %by_value = reverse %by_key; my $key = $by_value{$value}; That's not particularly efficient. It would be more space-efficient to use: while (my ($key, $value) = each %by_key) { $by_value{$value} = $key; } If your hash could have repeated values, the methods above will only find one of the associated keys. This may or may not worry you. If it does worry you, you can always reverse the hash into a hash of arrays instead: while (my ($key, $value) = each %by_key) { push @{$key_list_by_value{$value}}, $key; } How can I know how many entries are in a hash? (contributed by brian d foy) This is very similar to "How do I process an entire hash?", also in perlfaq4, but a bit simpler in the common cases. You can use the "keys()" built-in function in scalar context to find out have many entries you have in a hash: my $key_count = keys %hash; # must be scalar context! If you want to find out how many entries have a defined value, that's a bit different. You have to check each value. A "grep" is handy: my $defined_value_count = grep { defined } values %hash; You can use that same structure to count the entries any way that you like. If you want the count of the keys with vowels in them, you just test for that instead: my $vowel_count = grep { /[aeiou]/ } keys %hash; The "grep" in scalar context returns the count. If you want the list of matching items, just use it in list context instead: my @defined_values = grep { defined } values %hash; The "keys()" function also resets the iterator, which means that you may see strange results if you use this between uses of other hash operators such as "each()". How do I sort a hash (optionally by value instead of key)? (contributed by brian d foy) To sort a hash, start with the keys. In this example, we give the list of keys to the sort function which then compares them ASCIIbetically (which might be affected by your locale settings). The output list has the keys in ASCIIbetical order. Once we have the keys, we can go through them to create a report which lists the keys in ASCIIbetical order. my @keys = sort { $a cmp $b } keys %hash; foreach my $key ( @keys ) { printf "%-20s %6d\n", $key, $hash{$key}; } We could get more fancy in the "sort()" block though. Instead of comparing the keys, we can compute a value with them and use that value as the comparison. For instance, to make our report order case-insensitive, we use "lc" to lowercase the keys before comparing them: my @keys = sort { lc $a cmp lc $b } keys %hash; Note: if the computation is expensive or the hash has many elements, you may want to look at the Schwartzian Transform to cache the computation results. If we want to sort by the hash value instead, we use the hash key to look it up. We still get out a list of keys, but this time they are ordered by their value. my @keys = sort { $hash{$a} <=> $hash{$b} } keys %hash; From there we can get more complex. If the hash values are the same, we can provide a secondary sort on the hash key. my @keys = sort { $hash{$a} <=> $hash{$b} or "\L$a" cmp "\L$b" } keys %hash; How can I always keep my hash sorted? You can look into using the "DB_File" module and "tie()" using the $DB_BTREE hash bindings as documented in "In Memory Databases" in DB_File. The Tie::IxHash module from CPAN might also be instructive. Although this does keep your hash sorted, you might not like the slowdown you suffer from the tie interface. Are you sure you need to do this? :) What's the difference between "delete" and "undef" with hashes? Hashes contain pairs of scalars: the first is the key, the second is the value. The key will be coerced to a string, although the value can be any kind of scalar: string, number, or reference. If a key $key is present in %hash, "exists($hash{$key})" will return true. The value for a given key can be "undef", in which case $hash{$key} will be "undef" while "exists $hash{$key}" will return true. This corresponds to ($key, "undef") being in the hash. Pictures help... Here's the %hash table: keys values +------+------+ | a | 3 | | x | 7 | | d | 0 | | e | 2 | +------+------+ And these conditions hold $hash{'a'} is true $hash{'d'} is false defined $hash{'d'} is true defined $hash{'a'} is true exists $hash{'a'} is true (Perl 5 only) grep ($_ eq 'a', keys %hash) is true If you now say undef $hash{'a'} your table now reads: keys values +------+------+ | a | undef| | x | 7 | | d | 0 | | e | 2 | +------+------+ and these conditions now hold; changes in caps: $hash{'a'} is FALSE $hash{'d'} is false defined $hash{'d'} is true defined $hash{'a'} is FALSE exists $hash{'a'} is true (Perl 5 only) grep ($_ eq 'a', keys %hash) is true Notice the last two: you have an undef value, but a defined key! Now, consider this: delete $hash{'a'} your table now reads: keys values +------+------+ | x | 7 | | d | 0 | | e | 2 | +------+------+ and these conditions now hold; changes in caps: $hash{'a'} is false $hash{'d'} is false defined $hash{'d'} is true defined $hash{'a'} is false exists $hash{'a'} is FALSE (Perl 5 only) grep ($_ eq 'a', keys %hash) is FALSE See, the whole entry is gone! Why don't my tied hashes make the defined/exists distinction? This depends on the tied hash's implementation of EXISTS(). For example, there isn't the concept of undef with hashes that are tied to DBM* files. It also means that exists() and defined() do the same thing with a DBM* file, and what they end up doing is not what they do with ordinary hashes. How can I get the unique keys from two hashes? First you extract the keys from the hashes into lists, then solve the "removing duplicates" problem described above. For example: my %seen = (); for my $element (keys(%foo), keys(%bar)) { $seen{$element}++; } my @uniq = keys %seen; Or more succinctly: my @uniq = keys %{{%foo,%bar}}; Or if you really want to save space: my %seen = (); while (defined ($key = each %foo)) { $seen{$key}++; } while (defined ($key = each %bar)) { $seen{$key}++; } my @uniq = keys %seen; How can I make my hash remember the order I put elements into it? Use the Tie::IxHash from CPAN. use Tie::IxHash; tie my %myhash, 'Tie::IxHash'; for (my $i=0; $i<20; $i++) { $myhash{$i} = 2*$i; } my @keys = keys %myhash; # @keys = (0,1,2,3,...) Why does passing a subroutine an undefined element in a hash create it? (contributed by brian d foy) Are you using a really old version of Perl? Normally, accessing a hash key's value for a nonexistent key will *not* create the key. my %hash = (); my $value = $hash{ 'foo' }; print "This won't print\n" if exists $hash{ 'foo' }; Passing $hash{ 'foo' } to a subroutine used to be a special case, though. Since you could assign directly to $_[0], Perl had to be ready to make that assignment so it created the hash key ahead of time: my_sub( $hash{ 'foo' } ); print "This will print before 5.004\n" if exists $hash{ 'foo' }; sub my_sub { # $_[0] = 'bar'; # create hash key in case you do this 1; } Since Perl 5.004, however, this situation is a special case and Perl creates the hash key only when you make the assignment: my_sub( $hash{ 'foo' } ); print "This will print, even after 5.004\n" if exists $hash{ 'foo' }; sub my_sub { $_[0] = 'bar'; } However, if you want the old behavior (and think carefully about that because it's a weird side effect), you can pass a hash slice instead. Perl 5.004 didn't make this a special case: my_sub( @hash{ qw/foo/ } ); How can I make the Perl equivalent of a C structure/C++ class/hash or array of hashes or arrays? Usually a hash ref, perhaps like this: $record = { NAME => "Jason", EMPNO => 132, TITLE => "deputy peon", AGE => 23, SALARY => 37_000, PALS => [ "Norbert", "Rhys", "Phineas"], }; References are documented in perlref and perlreftut. Examples of complex data structures are given in perldsc and perllol. Examples of structures and object-oriented classes are in perlootut. How can I use a reference as a hash key? (contributed by brian d foy and Ben Morrow) Hash keys are strings, so you can't really use a reference as the key. When you try to do that, perl turns the reference into its stringified form (for instance, "HASH(0xDEADBEEF)"). From there you can't get back the reference from the stringified form, at least without doing some extra work on your own. Remember that the entry in the hash will still be there even if the referenced variable goes out of scope, and that it is entirely possible for Perl to subsequently allocate a different variable at the same address. This will mean a new variable might accidentally be associated with the value for an old. If you have Perl 5.10 or later, and you just want to store a value against the reference for lookup later, you can use the core Hash::Util::Fieldhash module. This will also handle renaming the keys if you use multiple threads (which causes all variables to be reallocated at new addresses, changing their stringification), and garbage-collecting the entries when the referenced variable goes out of scope. If you actually need to be able to get a real reference back from each hash entry, you can use the Tie::RefHash module, which does the required work for you. How can I check if a key exists in a multilevel hash? (contributed by brian d foy) The trick to this problem is avoiding accidental autovivification. If you want to check three keys deep, you might na?vely try this: my %hash; if( exists $hash{key1}{key2}{key3} ) { ...; } Even though you started with a completely empty hash, after that call to "exists" you've created the structure you needed to check for "key3": %hash = ( 'key1' => { 'key2' => {} } ); That's autovivification. You can get around this in a few ways. The easiest way is to just turn it off. The lexical "autovivification" pragma is available on CPAN. Now you don't add to the hash: { no autovivification; my %hash; if( exists $hash{key1}{key2}{key3} ) { ...; } } The Data::Diver module on CPAN can do it for you too. Its "Dive" subroutine can tell you not only if the keys exist but also get the value: use Data::Diver qw(Dive); my @exists = Dive( \%hash, qw(key1 key2 key3) ); if( ! @exists ) { ...; # keys do not exist } elsif( ! defined $exists[0] ) { ...; # keys exist but value is undef } You can easily do this yourself too by checking each level of the hash before you move onto the next level. This is essentially what Data::Diver does for you: if( check_hash( \%hash, qw(key1 key2 key3) ) ) { ...; } sub check_hash { my( $hash, @keys ) = @_; return unless @keys; foreach my $key ( @keys ) { return unless eval { exists $hash->{$key} }; $hash = $hash->{$key}; } return 1; } How can I prevent addition of unwanted keys into a hash? Since version 5.8.0, hashes can be *restricted* to a fixed number of given keys. Methods for creating and dealing with restricted hashes are exported by the Hash::Util module. Found in /usr/share/perl/5.34/pod/perlfaq7.pod How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regex}? You need to pass references to these objects. See "Pass by Reference" in perlsub for this particular question, and perlref for information on references. Passing Variables and Functions Regular variables and functions are quite easy to pass: just pass in a reference to an existing or anonymous variable or function: func( \$some_scalar ); func( \@some_array ); func( [ 1 .. 10 ] ); func( \%some_hash ); func( { this => 10, that => 20 } ); func( \&some_func ); func( sub { $_[0] ** $_[1] } ); Passing Filehandles As of Perl 5.6, you can represent filehandles with scalar variables which you treat as any other scalar. open my $fh, $filename or die "Cannot open $filename! $!"; func( $fh ); sub func { my $passed_fh = shift; my $line = <$passed_fh>; } Before Perl 5.6, you had to use the *FH or "\*FH" notations. These are "typeglobs"--see "Typeglobs and Filehandles" in perldata and especially "Pass by Reference" in perlsub for more information. Passing Regexes Here's an example of how to pass in a string and a regular expression for it to match against. You construct the pattern with the "qr//" operator: sub compare { my ($val1, $regex) = @_; my $retval = $val1 =~ /$regex/; return $retval; } $match = compare("old McDonald", qr/d.*D/i); Passing Methods To pass an object method into a subroutine, you can do this: call_a_lot(10, $some_obj, "methname") sub call_a_lot { my ($count, $widget, $trick) = @_; for (my $i = 0; $i < $count; $i++) { $widget->$trick(); } } Or, you can use a closure to bundle up the object, its method call, and arguments: my $whatnot = sub { $some_obj->obfuscate(@args) }; func($whatnot); sub func { my $code = shift; &$code(); } You could also investigate the can() method in the UNIVERSAL class (part of the standard perl distribution).
Generated by phpMan Author: Che Dong Under GNU General Public License
2026-06-02 18:25 @216.73.216.151 CrawledBy Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)