|
Home | Switchboard | Unix Administration | Red Hat | TCP/IP Networks | Neoliberalism | Toxic Managers |
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and bastardization of classic Unix |
|
Second look on scalar variables
Second look on hashes (Associative arrays)
Perl has just four basic types of variables:
|
All Perl variables have special prefixes that act much like "on the fly" declarations of the type. You can also think about $ of a function that converts to string a variable that it prefixed.
The main achievement of Perl in this area is the introduction of the undef value. This is a very interesting and pretty innovative solution to the problem of uninitialized variables.
Citing Variable Scoping in Perl the basics
Scalar variables in Perl always start with $ and can hold both strings and numbers. This is true and a scalar variable always has a string value and a numeric value. Yes, any string in Perl has a numeric value, and in case of non-numeric strings it always zero.. Like C Perl is case sensitive, so variables $a and $A are different.
Like C Perl is case sensitive, so variables $a and $A are different |
$price = 5.0; # this variable is assigned a numeric value print "price=$price"; # will print 5First Perl determines that left side of expression is well-formed numeric value. Then it will convert it to double-float (internal representation of numeric values in Perl). After than it will convert numeric value to string and will assign it to scalar on the right part (so string value of the scalar will be 5 not 5.0 as one would expect.
If you supply the number as a string literal than string value will be stored first. It will not be converted to numeric value:
$price= '5.0'; print "price=$price"; # will print 5.0
In general variable names consists of numbers, letters and underscores, but they should not start with a number and the names like $_ and several others are special, as we'll see later.
Many Perl operations return undef to indicate unusual situations -- failure, end of file, system error, uninitialized variable, and other exceptional conditions. There is a defined() function than allows you to check whether a variable contains the undef value. A conditional expression will not distinguish among undef, zero, the empty string, and "0", which are all considered to be false.
Note that since undef is a valid scalar, its presence doesn't necessarily indicate an exceptional condition: many built-in functions returns undef when there no output any more (but also in case when element happens to have the value undef.)
Use of built-in function defined() upon aggregates (hashes and arrays) is not guaranteed to produce intuitive results, and should probably be avoided. When used on the element of an associative array (hash -- see below), it tells you whether the value is defined, not whether the key exists in the hash. Use exists for the latter purpose.
One big advantage of interpreted languages is that they can check whether the variable was initialized or not. Here Perl provides a solution that is superior to any other I know of. It explicitly defines special undefined value and set of functions to check for this value.
You can check if the variable exists in the symbol table (was it initialized or not) by using special built-in function defined. All uninitialized variables are assumed to have a special value before they are assigned any explicitly -- this value is called undef. Paradoxically you can assign undef like any other value to variables. Logically this should mean that the variable is deleted from the symbol table, but I do not know whether this true in Perl or not. For example:
$arg1 = undef; # set to undef undef($arg1); # same as above
In Perl all uninitialized scalar variables are assumed to have the
value undef .
Please note that -w switch produce some partially useful warning about uninitialized variables and this is another case when it can be useful. |
That leads to the major difference between Perl and most of compiled languages (C, Pascal, etc.) -- a scalar variable can be used without initial assignment a value to it. In this case it has a default value undef that can be converted to string (resulting in zero length string) or to numeric value (resulting in 0).
In numeric operations the undef value is converted to zero much like and string literal. So it is perfectly legal to write
$k=$i+0;
Let's assume that at in this expression the variable $i is undefined and uninitialized. It is first created with initial value undef. Then because operator "+" requires numeric value it is converted to a numeric value (zero). Uninitialized value can also be used for comparison -- they will be converted according to the operator either to text value (zero length string) or numeric value (zero).
For arithmetic operations undef behaves like 0, |
If you need to test whether or not a scalar has initialized you can use defined function. For example, if argument was passed to a subroutine then the corresponding variable can be either defined or undefined. If it is not defined, then you need to assign default value to it providing Perl with the capability to set default variables to subroutine parameters. We will learn about them more later.
From logical standpoint you cannot use undef in comparison because the type of variable in Perl is determined by an operator and should be either numeric or string depending on context:
if ( $arg1 == undef ) {...} # undef will always be converted to zero first
The undef value is often used in Perl instead of exceptions to signal end of the data stream (Perl 5 does not support the notion of exceptions). For example as we will see in Ch.4, when you read the file and reach the end, the value undef is returned to signal that there is no more records in the file. Similarly functions can signal that there is no more values by returning the undef value.
Here is how defined if described in Perl documentation (perlfun):
Returns a Boolean value telling whether EXPR has a value other than the undefined value undef. If EXPR is not present, $_ will be checked.Many operations return undef to indicate failure, end of file, system error, uninitialized variable, and other exceptional conditions. This function allows you to distinguish undef from other values. (A simple Boolean test will not distinguish among undef, zero, the empty string, and "0", which are all equally false.) Note that since undef is a valid scalar, its presence doesn't necessarily indicate an exceptional condition: pop() returns undef when its argument is an empty array, or when the element to return happens to be undef.
You may also use defined() to check whether a subroutine exists, by saying defined &func without parentheses. On the other hand, use of defined() upon aggregates (hashes and arrays) is not guaranteed to produce intuitive results, and should probably be avoided.When used on a hash element, it tells you whether the value is defined, not whether the key exists in the hash. Use exists for the latter purpose.
(to be written)
Arrays allow to access to their elements by number. Array in Perl are quite different from arrays in C and are more like a buffer of a text editor with indexes as line numbers. There are two notation for arrays -- regular index notation and so called list notation. For example (1,2,3) is an array with three elements.
Like in C and unlike any text editor the first element of array has index zero. For example the first element of array @mybuffer is $mybuffer[0], the second element is $mybuffer[1], and so on.
One needs to use prefix @ for arrays and prefix $ for array elements. |
You can initialize arrays using list notation:
@x=(1,2,3) # now @x contains three elements $x[0], $x[1] and $x[2]
Negative indexes does not make sense in Perl arrays, but they are used to denote access to the end of the array, not from the start. The last element is $mybuffer[-1], the element before last is $mybuffer[-2], etc. This is quite convenient shortcut worth remembering.
Negative indexes are used to access elements |
Again, arrays in Perl are much more like lists (or buffers of text editors which are essentially lists) -- they have no lower or upper bound and can accept any type of variable (both numbers and strings). All array names are prefixed by an @ symbol, but elements are prefixed with $. For example:
@workweek = ("Mn", "Ts", "Wn", "Th","Fr"); # initialization of array @workweek with 5 values @weekend = ("St", "Sn");These statements assigns a five element list to the array variable @workweek and a two element list to the array variable @weekend.
Like in C the array is accessed by using indices starting from 0, and square brackets are used to specify the index. For example:
print $workweek[4]; # will print Fr. Notice symbol $ instead of @
This substitution of @ with $ is a frequent source of errors for beginners. Be careful. In this particular case there is some logic in this convention (after all each element of array is a scalar) and you need to adapt to it.
If you want to access one element of array you need to use a scalar like in $week[0]. Usage of @week[0] is a frequent error(this is interpreted as a slice -- see below). Watch your steps ! |
If index is non-numeric that 0 will used. So the following two statements are equal:
$color["abba"]="blue"; $color[0]="blue"; # same as above
Unlike C it is possible to specify multiple indexes. This is called a array slice or simply slice. For example
@x[1,2]=(3,4) # slice of array @x with indexes 1 and 2 is assigned values 3 and 4
Any slice in scalar context returns the last element of the slice, not the number of elements like an array. So
$s=@x[0]; # wrong way to assign $x[0] to a veriable $s
Slices accept Pascal range notation (..). for example
@x[2..5]=(1,2,3,4); @danger_levels[1..3]=('green','orange','red');
Arrays on the left side of assignment statement are evaluated before any operations on right side. That's mean that in Perl you can exchange two elements using:
($a,$b)=($b, $a);
Only uninitialized scalar variables in Perl have the undef value. Uninitialized arrays have the value of the empty list (). You can assign undef value to array and pretty logically it destroys the content of the array and free all the memory. The same effect can be achieved by assigning the array an empty list and this is a more common notation.
Unlike scalars the initial value of array is not undef
value, but an empty list (). |
You cannot shorten array or remove elements from array by assigning undef value to them. This not very logical but that's how it is. So here undef is a special value, not just the fact of absence of identifier in the symbol table like it the logical view on undef for scalars presuppose.
Arrays are classical data structure. So operations on arrays will be discussed in more details in the next chapter.
Associative arrays or hashes are a generalization of a regular arrays to a non numeric indexes. They provide a built in search capability . You put values into the hash by defining key-value pairs. Like Perl arrays, hashes grow and shrink automatically when you add or subtract elements. The main difference is that array indexes are converted to numeric before retrieving the value and in associative arrays they are converted to string and are usually arbitrary strings (for regular arrays all non-numeric indexes are equivalent to the index 0).
The second important difference is that associative array entries are not created on mere reference, like scalars.
To define an associative array we use the usual parenthesis notation, but the array itself is prefixed by a % sign. Suppose we want to create an array of url of sites and there IP addresses. It would look like this:
%ip =( "www.yahoo.com", "204.71.200.68", # note brackets "(" and ")" "www.google.com", "209.185.108.220", "www.northenlight.com", "128.11.1.1", );
As a cosmetic improvement we can replace ",' with "=>". this way it's easier to count pairs so it is a recommended notation in all cases where Perl script is written by human (in generated scripts notation above is simpler and can be preferable):
%ip = ( "www.yahoo.com" => "204.71.200.68", "www.google.com" => 209.185.108.220", "www.northenlight.com" => "128.11.1.1", );Now we can find the IP addresses of sited with the following expressions (note curly brackets):
$ip{"www.yahoo.com"}; # Returns 204.71.200.68 $ip{"www.northenlight.com"}; # Returns 128.11.1.1Notice that like in arrays to access elements of hash each % sign has been changed to a $ because that element is a scalar. Unlike list arrays, the index (in this case the person's name) is enclosed in curly braces.
An associative array can be converted back into a list array just by assigning it to a list array variable. Order of variable is underemined in this conversion. A list array can be converted into an associative array by assigning it to an associative array variable. each pair will be converted into one hash element. Logically the list array should have an even number of elements, but if not the value of the last will be undef.
@info = %ip; # @info is a list array. It
# now has 6 elements, but the order of pairs may changed
%ip=@info; # Reverse operation
If you wish to access a value, you can say:
print $ip{'www.yahoo.com'}; # note curly brackets
Again note that one needs to use prefix $ instead of %. To change the value you can also say:
$ip{'www.yahoo.com'} = '204.71.200.67';
Hashes are not lists, so there is no previous and next element related operations defined on hashes. If you try to get all of them, then the order in which Perl will extract values is undetermined and can be different from the order in which you put elements into the hash.
You can delete a single element of hash with the operator delete, for example:
delete $ip{'www.yahoo.com'};
Like arrays the initial value of hash is an associative array with no elements. So if you convert such hash to an array you will receive an empty list. Built-in function undef is applicable to hashes and will convert any hash to an empty one. As you will see in the next chapter you need to apply a special built-in function delete to remove element from the hash.
Hashes are non-traditional data structure and here Perl is a to certain extent a pioneer. We will discuss operations on hashes in more details in the next chapter.
Perl does not provide explicit facility for creating constant values, but there are some way around via typeglobs construct and/or the "use constant" pragma. All of them are deficient in implementation and clumsy to use:
*PI = \3.14159265358979;
use constant PI => 3.14159;Under the hood, this uses the subroutine slot of *PI, instead of the scalar slot used earlier. It's equivalent to the more compact (but less readable):
*PI = sub () { 3.14159 };Numeric constants cannot be interpolated into strings.
use constant HOSTS => '/etc/hosts'; %hash = ('HOSTS' => 'PE1950,PE2950', 'BLADES' => 'BL280c,BL460c,BL490c'); $some_value = $hash{HOSTS}; # wrong! Will be interpreted as $hash{"HOSTS"} $some_value = $hash{+HOSTS}; # right use of string constant
(who thinks to use a unary plus when using a hash?)
use constant MARRAY => ( 'jan','feb','mar','apr','may',jun',jul',aug',sep',nov','dec' ); $vacations = MARRAY[7]; # wrong! $vacations = (MARRAY)[7]; # right -- MUST use parentheses
There is also Readonly.pm but it imposes a performance penalty. In other words it's pretty slow and pretty complex. Not recommended. I think that this feature should be implemented on the language level via variable attributes ( which can similar to Unix file attributes) not via crutches.
|
Switchboard | ||||
Latest | |||||
Past week | |||||
Past month |
Sep 01, 2020 | perlmaven.com
How to get a slice of an array or an array reference?
Once you are done check out the other resources you can find on this site and consider supporting me via Patreon .Given an array listing rulers in the Kingdom of Jerusalem like this one: @kings = ('Baldwin', 'Melisende', 'Fulk', 'Amalric', 'Guy', 'Conrad') . How can we create one that is built from the 2nd, the 4th and then the 1st element?
One solution is:
@names = ($kings[2], $kings[4], $kings[1])
The other, the simpler solution is to use array slices:
@names = @kings[2,4,1]
In this case we use the @ prefix of the array and provide several indexes. If you are familiar with arrays in Perl , you surely remember that when we talk about the whole array we put @ in front of the name, but when we talk about a single element of an array we replace the @ sigil by the $ sigil and put square brackets at the end.
When we want create a list of one or more of the elements of the array we use the @ sigil again, as it represents "plural" and then we put one or more indexes in the square brackets after the name of the array.
See the full example here:
examples/array_slice.pl
Scalar value @kings[2] better written as $kings[2]
- use strict ;
- use warnings ;
- use 5.010 ;
- my @kings = ( 'Baldwin' , 'Melisende' , 'Fulk' , 'Amalric' , 'Guy' , 'Conrad' );
- my @names = ( $kings [ 2 ], $kings [ 4 ], $kings [ 1 ]);
- say join ', ' , @names ; # Fulk, Guy, Melisende
- my @slice = @kings [ 2 , 4 , 1 ];
- say join ', ' , @slice ; # Fulk, Guy, Melisende
This warning will appear if you try to use an array slice with a single index as in this example:
my @s = @kings[2];
This is how splain explains the warning:
Scalar value @kings[2] better written as $kings[2] at array_slice.pl line 14 (#1) (W syntax) You've used an array slice (indicated by @) to select a single element of an array. Generally it's better to ask for a scalar value (indicated by $). The difference is that $foo[&bar] always behaves like a scalar, both when assigning to it and when evaluating its argument, while @foo[&bar] behaves like a list when you assign to it, and provides a list context to its subscript, which can do weird things if you're expecting only one subscript.On the other hand, if you were actually hoping to treat the array element as a list, you need to look into how references work, because Perl will not magically convert between scalars and lists for you. See perlref.
If you would like to create a new array using a single element of another array then you should probably write:
my @s = $kings[2];
or if you want to make sure readers of your code won't be surprised by the assignment of a scalar to an array, then you can even put parentheses around the value.
my @s = ($kings[2]);
Slice of an array referenceIf we have out data in an ARRAY reference and not in an array, the code will be a bit more complex:
In this case we have a variable called $kings which is a reference to an array.
In the plain version, when we use individual elements we just need to dereference the ARRAY reference for each individual element.
my @names = ($kings->[2], $kings->[4], $kings->[1]);
If we would like to use the array slice syntax then first we need to dereference the whole array putting the @ sigil in-front of the reference: @$kings , but then we can simply put the square brackets behind that construct: my @slice = @$kings[2,4,1]; though I think I prefer the version when we put curly braces around the reference, thereby making it clear that it is a single unit of expression:
my @slice = @{$kings}[2,4,1];
The full example can be seen here:
examples/array_ref_slice.pl
- use strict ;
- use warnings ;
- use 5.010 ;
- my $kings = [ 'Baldwin' , 'Melisende' , 'Fulk' , 'Amalric' , 'Guy' , 'Conrad' ];
- my @names = ( $kings ->[ 2 ], $kings ->[ 4 ], $kings ->[ 1 ]);
- say join ', ' , @names ; # Fulk, Guy, Melisende
- my @slice = @{ $kings }[ 2 , 4 , 1 ];
- say join ', ' , @slice ; # Fulk, Guy, Melisende
Aug 19, 2020 | perldoc.perl.org
Perl functions A-Z | Perl functions by category | The 'perlfunc' manpage
- splice ARRAY,OFFSET,LENGTH,LIST
- splice ARRAY,OFFSET,LENGTH
- splice ARRAY,OFFSET
- splice ARRAY
Removes the elements designated by OFFSET and LENGTH from an array, and replaces them with the elements of LIST, if any. In list context, returns the elements removed from the array. In scalar context, returns the last element removed, or undef if no elements are removed. The array grows or shrinks as necessary. If OFFSET is negative then it starts that far from the end of the array. If LENGTH is omitted, removes everything from OFFSET onward. If LENGTH is negative, removes the elements from OFFSET onward except for -LENGTH elements at the end of the array. If both OFFSET and LENGTH are omitted, removes everything. If OFFSET is past the end of the array and a LENGTH was provided, Perl issues a warning, and splices at the end of the array.
The following equivalences hold (assuming
$#a >= $i
)
- push ( @a , $x , $y ) splice ( @a , @a , 0 , $x , $y )
- pop ( @a ) splice ( @a , -1 )
- shift ( @a ) splice ( @a , 0 , 1 )
- unshift ( @a , $x , $y ) splice ( @a , 0 , 0 , $x , $y )
- $a [ $i ] = $y splice ( @a , $i , 1 , $y )
splice can be used, for example, to implement n-ary queue processing:
- sub nary_print {
- my $n = shift ;
- while ( my @next_n = splice @_ , 0 , $n ) {
- say join q{ -- } , @next_n ;
- }
- }
- nary_print ( 3 , qw(a b c d e f g h) ) ;
- # prints:
- # a -- b -- c
- # d -- e -- f
- # g -- h
Starting with Perl 5.14, an experimental feature allowed splice to take a scalar expression. This experiment has been deemed unsuccessful, and was removed as of Perl 5.24.
Jan 01, 2009 | stackoverflow.com
How do I add an array ref to the middle of an existing array in Perl? Ask Question Asked 11 years, 2 months ago Active 6 years, 7 months ago Viewed 6k times
https://tpc.googlesyndication.com/safeframe/1-0-37/html/container.html Report this ad
, 2009-06-22 03:09:37
I want to be able to place an array into an array. For example, I may have an array like this:
my @array1 = ("element 1","element 2","element 3");Then I have another array
my $array_ref = ["this will", "go between", "element 1 and 2"];I want to place
$array_ref
into the first so that the first array looks like this:("element 1",["this will", "go between", "element 1 and 2"],"element 2","element 3")I can't seem to do this. I looked all over Google and found nothing.
Telemachus ,
The second one is not an array. It is an array reference. – Alan Haggai Alavi Jun 22 '09 at 4:26ysth , 2009-06-22 03:28:29
So you use splice to replace 0 elements beginning with element 1 (the second element, the first is element 0) with your desired elements:
splice( @array, 1, 0, ["this will", "go between", "element 1 and 2"] );Or possibly you mean:
splice( @array, 1, 0, "this will", "go between", "element 1 and 2" );if you don't want nested arrays.
Nic Gibson ,
I think he meant insert into an existing array too. Not totally clear though. – Nic Gibson Jun 22 '09 at 8:47aks ,
The important point to remember is the distinction between () and []. '()' gives you a list of elements, for eg. (1, 2, 3) which you could then assign to an array variable as so -
my @listOfElem = (1, 2, 3);'[]' is an array reference and returns a scalar value which you could incorporate into your list.
my $refToElem = ['a', 'b', 'c'];In your case, if you are initializing the first array then you could simply insert the second array elements like so,
my @listOfElem = (1, 2, ['a', 'b', 'c'], 3); #This gives you a list of "4" elements with the third #one being an array reference my @listOfElem = (1, 2, $refToELem, 3); #Same as above, here we insert a reference scalar variable my @secondListOfElem = ('a', 'b', 'c'); my @listOfElem = (1, 2, \@secondListOfElem, 3); #Same as above, instead of using a scalar, we insert a reference #to an existing array which, presumably, is what you want to do. #To access the array within the array you would write - $listOfElem[2]->[0] #Returns 'a' @{listOfElem[2]}[0] #Same as above.If you have to add the array elements on the fly in the middle of the array then just use 'splice' as detailed in the other posts.
> ,
add a commentbrian d foy , 2009-06-22 13:36:27
This is the sort of thing you'll understand after going through the first part of Intermediate Perl , which covers references and data structures. You can also look in the Perl data structures cookbook .
In short, you store an array in another array by using a reference (which is just a scalar):
my @big_array = ( $foo, $bar, \@other_array, $baz );In your case, you used the anonymous array constructor and just want to splice it into an existing array. There's nothing special about it being an array reference:
splice @big_array, $offset, $length, @new_items;In your case, you wanted to start at element 1, remove 0 items, and add your reference:
splice @big_array, 1, 0, $array_ref;> ,
add a commentanonymous coward , 2009-06-22 03:18:52
Try having a temporary array, like this:
@temp_arr = ("this will", "go between", "element 1 and 3"); @my_arr = ("element 1", \@temp_arr, "element 3");You can use the sub-elements like this:
print $my_arr[1]->[0]; # prints 'this will'Refer to the subarray like this:
print @$my_arr[1]; # Right! Prints 'this willgo betweenelement 1 and 2' # Don't do this: print $my_arr[1]; # Wrong! Prints something like: 'ARRAY(0xDEADBEEF)'Ape-inago ,
I agree, use references. – Ape-inago Jun 22 '09 at 3:20Alan Haggai Alavi , 2009-06-22 04:35:10
What you have is an array and an array reference.
#!/usr/bin/perl use strict; use warnings; my @array = ("element 1","element 2","element 3"); my $arrayref = ["this will", "go between", "element 1 and 2"]; splice( @array, 1, 0, $arrayref ); # Grow the array with the list (which is $arrayref) for ( my $i = 0; $i <= $#array; $i++ ) { print "\@array[$i] = $array[$i]\n"; }> ,
add a comment> ,
Use splice .
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @array1 = ("element 1", "element 2", "element 3"); my $array_ref = ["this will", "go between", "element 1 and 2"]; splice(@array1, 1, 0, $array_ref); print Dumper \@array1;This will print the following:
$VAR1 = [ 'element 1', [ 'this will', 'go between', 'element 1 and 2' ], 'element 2', 'element 3' ];
Aug 13, 2020 | www.perlmonks.org
by zapdos
on Aug 11, 2020 at 02:09 UTC ( # 11120582 = perlquestion : print w/replies , xml ) Need Help?? zapdos has asked for the wisdom of the Perl Monks concerning the following question:
- log likbez out
- likbez
- The Monastery Gates
- Seekers of Perl Wisdom
- Meditations
- Cool Uses For Perl
- Obfuscation
- Q&A
- Tutorials
- Poetry
- Reviews
- Perl News
- Donate
- Recent Threads
- Newest Nodes
- Super Search
- PerlMonks Discussion
- What's New
$rocks[0] = 'bedrock'; $rocks[1] = 'slate'; $rocks[2]= 'lava'; $rocks[3] = 'crushed rock'; $rocks[99] = 'schist'; $#rocks = 2; # forget all rocks after 'lava' $#rocks = 99; # add 97 undef elements (the forgotten rocks are gone forever)So I'm following the book Learning Perl, there's this code with comments in it: If I do print $rocks[$#rocks]; it prints nothing. Why? When I comment out $#rocks = 99; it prints 'lava' and when I comment out $#rocks = 2; it prints 'schist'.But when I maintain the two it prints nothing as I already said.
And what the comments "add 97 undef elements (the forgotten rocks are gone forever)" and "forget all rocks after 'lava'" mean?
Jan 01, 2012 | stackoverflow.com
Ask Question Asked 7 years, 5 months ago Active 2 years, 8 months ago Viewed 12k times
Charles , 2012-05-31 20:50:19
I'm looking for advice on Perl best practices. I wrote a script which had a complicated regular expression:my $regex = qr/complicated/; # ... sub foo { # ... if (/$regex/) # ... }where
foo
is a function which is called often, and$regex
is not used outside that function. What is the best way to handle situations like this? I only want it to be interpreted once, since it's long and complicated. But it seems a bit questionable to have it in global scope since it's only used in that sub. Is there a reasonable way to declare it static?A similar issue arises with another possibly-unjustified global. It reads in the current date and time and formats it appropriately. This is also used many times, and again only in one function. But in this case it's even more important that it not be re-initialized, since I want all instances of the date-time to be the same from a given invocation of the script, even if the minutes roll over during execution.
At the moment I have something like
my ($regex, $DT); sub driver { $regex = qr/complicated/; $DT = dateTime(); # ... } # ... driver();which at least slightly segregates it. But perhaps there are better ways.
Again: I'm looking for the right way to do this, in terms of following best practices and Perl idioms. Performance is nice but readability and other needs take priority if I can't have everything.
hobbs ,
If you're using perl 5.10+, use astate
variable.use feature 'state'; # use 5.010; also works sub womble { state $foo = something_expensive(); return $foo ** 2; }will only call
something_expensive
once.If you need to work with older perls, then use a lexical variable in an outer scope with an extra pair of braces:
{ my $foo = something_expensive(); sub womble { return $foo ** 2; } }this keeps
$foo
from leaking to anyone except forwomble
.ikegami , 2012-05-31 21:14:04
Is there any interpolation in the pattern? If not, the pattern will only be compiled once no matter how many times the qr// is executed.$ perl -Mre=debug -e'qr/foo/ for 1..10' 2>&1 | grep Compiling | wc -l 1 $ perl -Mre=debug -e'qr/foo$_/ for 1..10' 2>&1 | grep Compiling | wc -l 10Even if there is interpolation, the pattern will only be compiled if the interpolated variables have changed.
$ perl -Mre=debug -e'$x=123; qr/foo$x/ for 1..10;' 2>&1 | grep Compiling | wc -l 1 $ perl -Mre=debug -e'qr/foo$_/ for 1..10' 2>&1 | grep Compiling | wc -l 10Otherwise, you can use
{ my $re = qr/.../; sub foo { ... /$re/ ... } }or
use feature qw( state ); sub foo { state $re = qr/.../; ... /$re/ ... }Alan Rocker , 2014-07-02 16:25:27
Regexes can be specified with the "o" modifier, which says "compile pattern once only" - in the 3rd. edition of the Camel, see p. 147zoul ,
There's a state keyword that might be a good fit for this situation:sub foo { state $regex = /.../; ... }TrueY , 2015-01-23 10:14:12
I would like to completeikegami
's great answer. Some more words I would like to waste on the definition of local variables in pre 5.10 perl .Let's see a simple example code:
#!/bin/env perl use strict; use warnings; { # local my $local = "After Crying"; sub show { print $local,"\n"; } } # local sub show2; show; show2; exit; { # local my $local = "Solaris"; sub show2 { print $local,"\n"; } } # localThe user would expect that both
sub
will print the local variable, but this is not true!Output:
After Crying Use of uninitialized value $local in print at ./x.pl line 20.The reason is that
show2
is parsed, but the initialization of the local variable is not executed! (Of course ifexit
is removed and ashow2
is added at the end,Solaris
will be printed in the thirds line)This can be fixed easily:
{ # local my $local; BEGIN { $local = "Solaris"; } sub show2 { print $local,"\n"; } } # localAnd now the output what was expected:
After Crying SolarisBut
state
in 5.10+ is a better choice...I hope this helps!
Nov 14, 2019 | stackoverflow.com
Asked 7 years, 7 months ago Active 7 years, 7 months ago Viewed 20k times 8 1
brian d foy ,Jul 17, 2014 at 17:54
How do I change the value of a variable in the package used by a module so that subroutines in that module can use it?Here's my test case:
testmodule.pm:
package testmodule; use strict; use warnings; require Exporter; our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); @ISA = qw(Exporter); @EXPORT = qw(testsub); my $greeting = "hello testmodule"; my $var2; sub testsub { printf "__PACKAGE__: %s\n", __PACKAGE__; printf "\$main::greeting: %s\n", $main::greeting; printf "\$greeting: %s\n", $greeting; printf "\$testmodule::greeting: %s\n", $testmodule::greeting; printf "\$var2: %s\n", $var2; } # End testsub 1;testscript.pl:
#!/usr/bin/perl -w use strict; use warnings; use testmodule; our $greeting = "hello main"; my $var2 = "my var2 in testscript"; $testmodule::greeting = "hello testmodule from testscript"; $testmodule::var2 = "hello var2 from testscript"; testsub();output:
Name "testmodule::var2" used only once: possible typo at ./testscript.pl line 11. __PACKAGE__: testmodule $main::greeting: hello main $greeting: hello testmodule $testmodule::greeting: hello testmodule from testscript Use of uninitialized value $var2 in printf at testmodule.pm line 20. $var2:I expected
$greeting
and$testmodule::greeting
to be the same since the package of the subroutine istestmodule
.I guess this has something to do with the way
use
d modules areeval
d as if in aBEGIN
block, but I'd like to understand it better.I was hoping to set the value of the variable from the main script and use it in the module's subroutine without using the fully-qualified name of the variable.
perl-user ,Sep 5, 2013 at 13:58
As you found out, when you usemy
, you are creating a locally scoped non-package variable. To create a package variable, you useour
and notmy
:my $foo = "this is a locally scoped, non-package variable"; our $bar = "This is a package variable that's visible in the entire package";Even better:
{ my $foo = "This variable is only available in this block"; our $bar = "This variable is available in the whole package": } print "$foo\n"; #Whoops! Undefined variable print "$bar\n"; #Bar is still defined even out of the blockWhen you don't put
use strict
in your program, all variables defined are package variables. That's why when you don't put it, it works the way you think it should and putting it in breaks your program.However, as you can see in the following example, using
Fileour
will solve your dilemma:Local/Foo.pm
#! /usr/local/bin perl package Local::Foo; use strict; use warnings; use feature qw(say); use Exporter 'import'; our @EXPORT = qw(testme); our $bar = "This is the package's bar value!"; sub testme { # $foo is a locally scoped, non-package variable. It's undefined and an error say qq(The value of \$main::foo is "$main::foo"); # $bar is defined in package main::, and will print out say qq(The value of \$main::bar is "$main::bar"); # These both refer to $Local::Foo::bar say qq(The value of \$Local::Foo::bar is "$Local::Foo::bar"); say qq(The value of bar is "$bar"); } 1;Filetest.pl
#! /usr/local/bin perl use strict; use warnings; use feature qw(say); use Local::Foo; my $foo = "This is foo"; our $bar = "This is bar"; testme; say ""; $Local::Foo::bar = "This is the NEW value for the package's bar"; testmeAnd, the output is:
Use of uninitialized value $foo in concatenation (.) or string at Local/Foo.pm line 14. The value of $main::foo is "" The value of $main::bar is "This is bar" The value of $Local::Foo::bar is "This is the package's bar value!" The value of bar is "This is the package's bar value!" Use of uninitialized value $foo in concatenation (.) or string at Local/Foo.pm line 14. The value of $main::foo is "" The value of $main::bar is "This is bar" The value of $Local::Foo::bar is "This is the NEW value for the package's bar" The value of bar is "This is the NEW value for the package's bar"The error message you're getting is the result of
$foo
being a local variable, and thus isn't visible inside the package. Meanwhile,$bar
is a package variable and is visible.Sometimes, it can be a bit tricky:
if ($bar -eq "one") { my $foo = 1; } else { my $foo = 2; } print "Foo = $foo\n";That doesn't work because
$foo
only bas a value inside theif
block. You have to do this:my $foo; if ($bar -eq "one") { $foo = 1; } else { $foo = 2; } print "Foo = $foo\n"; #This works!Yes, it can be a bit to get your head wrapped around it initially, but the use of
use strict;
anduse warnings;
is now de rigueur and for good reasons. The use ofuse strict;
anduse warnings;
probably has eliminated 90% of the mistakes people make in Perl. You can't make a mistake of setting the value of$foo
in one part of the program, and attempting to use$Foo
in another. It's one of the things I really miss in Python.> ,
After reading Variable Scoping in Perl: the basics more carefully, I realized that a variable declared withmy
isn't in the current package. For example, in a simple script with no modules if I declaremy $var = "hello"
$main::var
still doesn't have a value.The way that this applies in this case is in the module. Since
my $greeting
is declared in the file, that hides the package's version of$greeting
and that's the value which the subroutine sees. If I don't declare the variable first, the subroutine would see the package variable, but it doesn't get that far because Iuse strict
.If I don't
use strict
and don't declaremy $greeting
, it works as I would have expected. Another way to get the intended value and not breakuse strict
is to useour $greeting
. The difference being that my declares a variable in the current scope while our declares a variable in the current package .
Nov 13, 2019 | stackoverflow.com
Paul Tomblin ,Oct 19, 2010 at 13:38
I want to repeatedly search for values in an array that does not change.So far, I have been doing it this way: I put the values in a hash (so I have an array and a hash with essentially the same contents) and I search the hash using
exists
.I don't like having two different variables (the array and the hash) that both store the same thing; however, the hash is much faster for searching.
I found out that there is a
~~
(smartmatch) operator in Perl 5.10. How efficient is it when searching for a scalar in an array?> ,
If you want to search for a single scalar in an array, you can use List::Util 'sfirst
subroutine. It stops as soon as it knows the answer. I don't expect this to be faster than a hash lookup if you already have the hash , but when you consider creating the hash and having it in memory, it might be more convenient for you to just search the array you already have.As for the smarts of the smart-match operator, if you want to see how smart it is, test it. :)
There are at least three cases you want to examine. The worst case is that every element you want to find is at the end. The best case is that every element you want to find is at the beginning. The likely case is that the elements you want to find average out to being in the middle.
Now, before I start this benchmark, I expect that if the smart match can short circuit (and it can; its documented in perlsyn ), that the best case times will stay the same despite the array size, while the other ones get increasingly worse. If it can't short circuit and has to scan the entire array every time, there should be no difference in the times because every case involves the same amount of work.
Here's a benchmark:
#!perl use 5.12.2; use strict; use warnings; use Benchmark qw(cmpthese); my @hits = qw(A B C); my @base = qw(one two three four five six) x ( $ARGV[0] || 1 ); my @at_end = ( @base, @hits ); my @at_beginning = ( @hits, @base ); my @in_middle = @base; splice @in_middle, int( @in_middle / 2 ), 0, @hits; my @random = @base; foreach my $item ( @hits ) { my $index = int rand @random; splice @random, $index, 0, $item; } sub count { my( $hits, $candidates ) = @_; my $count; foreach ( @$hits ) { when( $candidates ) { $count++ } } $count; } cmpthese(-5, { hits_beginning => sub { my $count = count( \@hits, \@at_beginning ) }, hits_end => sub { my $count = count( \@hits, \@at_end ) }, hits_middle => sub { my $count = count( \@hits, \@in_middle ) }, hits_random => sub { my $count = count( \@hits, \@random ) }, control => sub { my $count = count( [], [] ) }, } );div class="answercell post-layout--right,
Here's how the various parts did. Note that this is a logarithmic plot on both axes, so the slopes of the plunging lines aren't as close as they look:So, it looks like the smart match operator is a bit smart, but that doesn't really help you because you still might have to scan the entire array. You probably don't know ahead of time where you'll find your elements. I expect a hash will perform the same as the best case smart match, even if you have to give up some memory for it.
Okay, so the smart match being smart times two is great, but the real question is "Should I use it?". The alternative is a hash lookup, and it's been bugging me that I haven't considered that case.
As with any benchmark, I start off thinking about what the results might be before I actually test them. I expect that if I already have the hash, looking up a value is going to be lightning fast. That case isn't a problem. I'm more interested in the case where I don't have the hash yet. How quickly can I make the hash and lookup a key? I expect that to perform not so well, but is it still better than the worst case smart match?
Before you see the benchmark, though, remember that there's almost never enough information about which technique you should use just by looking at the numbers. The context of the problem selects the best technique, not the fastest, contextless micro-benchmark. Consider a couple of cases that would select different techniques:
- You have one array you will search repeatedly
- You always get a new array that you only need to search once
- You get very large arrays but have limited memory
Now, keeping those in mind, I add to my previous program:
my %old_hash = map {$_,1} @in_middle; cmpthese(-5, { ..., new_hash => sub { my %h = map {$_,1} @in_middle; my $count = 0; foreach ( @hits ) { $count++ if exists $h{$_} } $count; }, old_hash => sub { my $count = 0; foreach ( @hits ) { $count++ if exists $old_hash{$_} } $count; }, control_hash => sub { my $count = 0; foreach ( @hits ) { $count++ } $count; }, } );Here's the plot. The colors are a bit difficult to distinguish. The lowest line there is the case where you have to create the hash any time you want to search it. That's pretty poor. The highest two (green) lines are the control for the hash (no hash actually there) and the existing hash lookup. This is a log/log plot; those two cases are faster than even the smart match control (which just calls a subroutine).
There are a few other things to note. The lines for the "random" case are a bit different. That's understandable because each benchmark (so, once per array scale run) randomly places the hit elements in the candidate array. Some runs put them a bit earlier and some a bit later, but since I only make the
@random
array once per run of the entire program, they move around a bit. That means that the bumps in the line aren't significant. If I tried all positions and averaged, I expect that "random" line to be the same as the "middle" line.Now, looking at these results, I'd say that a smart-match is much faster in its worst case than the hash lookup is in its worst case. That makes sense. To create a hash, I have to visit every element of the array and also make the hash, which is a lot of copying. There's no copying with the smart match.
Here's a further case I won't examine though. When does the hash become better than the smart match? That is, when does the overhead of creating the hash spread out enough over repeated searches that the hash is the better choice?
,
Fast for small numbers of potential matches, but not faster than the hash. Hashes are really the right tool for testing set membership. Since hash access is O(log n) and smartmatch on an array is still O(n) linear scan (albeit short-circuiting, unlike grep), with larger numbers of values in the allowed matches, smartmatch gets relatively worse. Benchmark code (matching against 3 values):#!perl use 5.12.0; use Benchmark qw(cmpthese); my @hits = qw(one two three); my @candidates = qw(one two three four five six); # 50% hit rate my %hash; @hash{@hits} = (); sub count_hits_hash { my $count = 0; for (@_) { $count++ if exists $hash{$_}; } $count; } sub count_hits_smartmatch { my $count = 0; for (@_) { $count++ when @hits; } $count; } say count_hits_hash(@candidates); say count_hits_smartmatch(@candidates); cmpthese(-5, { hash => sub { count_hits_hash((@candidates) x 1000) }, smartmatch => sub { count_hits_smartmatch((@candidates) x 1000) }, } );Benchmark results:Rate smartmatch hash smartmatch 404/s -- -65% hash 1144/s 183% --
Nov 11, 2019 | stackoverflow.com
- Home
- Public
- Stack Overflow
- Tags
- Users
- Jobs
- Teams What's this?
Teams
Q&A for Work
Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information.
Learn more- First 10 Free
- How fast is Perl's smartmatch operator when searching for a scalar in an array? Ask Question Asked 8 years, 11 months ago Active 3 years ago Viewed 5k times 18 6
Paul Tomblin ,Oct 19, 2010 at 13:38
I want to repeatedly search for values in an array that does not change.So far, I have been doing it this way: I put the values in a hash (so I have an array and a hash with essentially the same contents) and I search the hash using
exists
.I don't like having two different variables (the array and the hash) that both store the same thing; however, the hash is much faster for searching.
I found out that there is a
~~
(smartmatch) operator in Perl 5.10. How efficient is it when searching for a scalar in an array?> ,
If you want to search for a single scalar in an array, you can use List::Util 'sfirst
subroutine. It stops as soon as it knows the answer. I don't expect this to be faster than a hash lookup if you already have the hash , but when you consider creating the hash and having it in memory, it might be more convenient for you to just search the array you already have.As for the smarts of the smart-match operator, if you want to see how smart it is, test it. :)
There are at least three cases you want to examine. The worst case is that every element you want to find is at the end. The best case is that every element you want to find is at the beginning. The likely case is that the elements you want to find average out to being in the middle.
Now, before I start this benchmark, I expect that if the smart match can short circuit (and it can; its documented in perlsyn ), that the best case times will stay the same despite the array size, while the other ones get increasingly worse. If it can't short circuit and has to scan the entire array every time, there should be no difference in the times because every case involves the same amount of work.
Here's a benchmark:
#!perl use 5.12.2; use strict; use warnings; use Benchmark qw(cmpthese); my @hits = qw(A B C); my @base = qw(one two three four five six) x ( $ARGV[0] || 1 ); my @at_end = ( @base, @hits ); my @at_beginning = ( @hits, @base ); my @in_middle = @base; splice @in_middle, int( @in_middle / 2 ), 0, @hits; my @random = @base; foreach my $item ( @hits ) { my $index = int rand @random; splice @random, $index, 0, $item; } sub count { my( $hits, $candidates ) = @_; my $count; foreach ( @$hits ) { when( $candidates ) { $count++ } } $count; } cmpthese(-5, { hits_beginning => sub { my $count = count( \@hits, \@at_beginning ) }, hits_end => sub { my $count = count( \@hits, \@at_end ) }, hits_middle => sub { my $count = count( \@hits, \@in_middle ) }, hits_random => sub { my $count = count( \@hits, \@random ) }, control => sub { my $count = count( [], [] ) }, } );div class="answercell post-layout--right,
Here's how the various parts did. Note that this is a logarithmic plot on both axes, so the slopes of the plunging lines aren't as close as they look:So, it looks like the smart match operator is a bit smart, but that doesn't really help you because you still might have to scan the entire array. You probably don't know ahead of time where you'll find your elements. I expect a hash will perform the same as the best case smart match, even if you have to give up some memory for it.
Okay, so the smart match being smart times two is great, but the real question is "Should I use it?". The alternative is a hash lookup, and it's been bugging me that I haven't considered that case.
As with any benchmark, I start off thinking about what the results might be before I actually test them. I expect that if I already have the hash, looking up a value is going to be lightning fast. That case isn't a problem. I'm more interested in the case where I don't have the hash yet. How quickly can I make the hash and lookup a key? I expect that to perform not so well, but is it still better than the worst case smart match?
Before you see the benchmark, though, remember that there's almost never enough information about which technique you should use just by looking at the numbers. The context of the problem selects the best technique, not the fastest, contextless micro-benchmark. Consider a couple of cases that would select different techniques:
- You have one array you will search repeatedly
- You always get a new array that you only need to search once
- You get very large arrays but have limited memory
Now, keeping those in mind, I add to my previous program:
my %old_hash = map {$_,1} @in_middle; cmpthese(-5, { ..., new_hash => sub { my %h = map {$_,1} @in_middle; my $count = 0; foreach ( @hits ) { $count++ if exists $h{$_} } $count; }, old_hash => sub { my $count = 0; foreach ( @hits ) { $count++ if exists $old_hash{$_} } $count; }, control_hash => sub { my $count = 0; foreach ( @hits ) { $count++ } $count; }, } );Here's the plot. The colors are a bit difficult to distinguish. The lowest line there is the case where you have to create the hash any time you want to search it. That's pretty poor. The highest two (green) lines are the control for the hash (no hash actually there) and the existing hash lookup. This is a log/log plot; those two cases are faster than even the smart match control (which just calls a subroutine).
There are a few other things to note. The lines for the "random" case are a bit different. That's understandable because each benchmark (so, once per array scale run) randomly places the hit elements in the candidate array. Some runs put them a bit earlier and some a bit later, but since I only make the
@random
array once per run of the entire program, they move around a bit. That means that the bumps in the line aren't significant. If I tried all positions and averaged, I expect that "random" line to be the same as the "middle" line.Now, looking at these results, I'd say that a smart-match is much faster in its worst case than the hash lookup is in its worst case. That makes sense. To create a hash, I have to visit every element of the array and also make the hash, which is a lot of copying. There's no copying with the smart match.
Here's a further case I won't examine though. When does the hash become better than the smart match? That is, when does the overhead of creating the hash spread out enough over repeated searches that the hash is the better choice?
,
Fast for small numbers of potential matches, but not faster than the hash. Hashes are really the right tool for testing set membership. Since hash access is O(log n) and smartmatch on an array is still O(n) linear scan (albeit short-circuiting, unlike grep), with larger numbers of values in the allowed matches, smartmatch gets relatively worse. Benchmark code (matching against 3 values):#!perl use 5.12.0; use Benchmark qw(cmpthese); my @hits = qw(one two three); my @candidates = qw(one two three four five six); # 50% hit rate my %hash; @hash{@hits} = (); sub count_hits_hash { my $count = 0; for (@_) { $count++ if exists $hash{$_}; } $count; } sub count_hits_smartmatch { my $count = 0; for (@_) { $count++ when @hits; } $count; } say count_hits_hash(@candidates); say count_hits_smartmatch(@candidates); cmpthese(-5, { hash => sub { count_hits_hash((@candidates) x 1000) }, smartmatch => sub { count_hits_smartmatch((@candidates) x 1000) }, } );Benchmark results:Rate smartmatch hash smartmatch 404/s -- -65% hash 1144/s 183% --
Oct 13, 2019 | perlmaven.com
In response to an earlier article about undef one of the readers asked me:How do you eliminate a value in the middle of an array in Perl?
I am not sure if undef and eliminating values from an array are related, though I guess, if we see having a value of undef as being "empty", then I can understand the connection. In general though, setting something to be undef and deleting something is not the same.
Are you serious about Perl? Check out my Beginner Perl Maven book .
I have written it for you!Let's see first how we can set an element of an array to be undef and then how we can delete an element from an array.
We start with the following code:
- use Data :: Dumper qw ( Dumper );
- my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
- print Dumper \@dwarfs ;
When printed using Data::Dumper we get the following output:
$VAR1 = [ 'Doc', 'Grumpy', 'Happy', 'Sleepy', 'Sneezy', 'Dopey', 'Bashful' ];Set an element to undefUsing the return value of the undef() function:
- use Data :: Dumper qw ( Dumper );
- my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
- $dwarfs [ 3 ] = undef ;
- print Dumper \@dwarfs ;
This code will set element 3 (the 4th element of the array) to undef , but will NOT change the size of the array:
$VAR1 = [ 'Doc', 'Grumpy', 'Happy', undef, 'Sneezy', 'Dopey', 'Bashful' ];Using the undef() function directly on an element of an array yields similar results:
- use Data :: Dumper qw ( Dumper );
- my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
- undef $dwarfs [ 3 ];
- print Dumper \@dwarfs ;
So for our purposes $dwarfs[3] = undef; and undef $dwarfs[3]; do the same thing. They both can set a value to be undef .
Removing an element from the array using spliceThe splice function can totally eliminate the value from the array:
- use Data :: Dumper qw ( Dumper );
- my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
- splice @dwarfs,3,1;
- print Dumper \@dwarfs ;
$VAR1 = [ 'Doc', 'Grumpy', 'Happy', 'Sneezy', 'Dopey', 'Bashful' ];As you can see, in this case the array became one element shorter as we have removed one of the elements from the middle of the array.
This is how you can delete an element from an array .
Oct 09, 2019 | perlmaven.com
Prev Next In most of the cases we either want a variable to be accessible only from inside a small scope, inside a function or even inside a loop. These variables get created when we enter the function (or the scope created by a a block) and destroyed when we leave the scope.In some cases, especially when we don't want to pay attention to our code, we want variables to be global, to be accessible from anywhere in our script and be destroyed only when the script ends. In General having such global variables is not a good practice.
In some cases we want a variable to stay alive between function calls, but still to be private to that function. We want it to retain its value between calls.
Are you serious about Perl? Check out my Beginner Perl Maven book .
I have written it for you!In the C programming language one can designate a variable to be a static variable . This means it gets initialized only once and it sticks around retaining its old value between function calls.
In Perl, the same can be achieved using the state variable which is available starting from version 5.10, but there is a construct that will work in every version of Perl 5. In a way it is even more powerful.
Let's create a counter as an example:
state variable
- use strict ;
- use warnings ;
- use 5.010 ;
- sub count {
- state $counter = 0 ;
- $counter ++;
- return $counter ;
- }
- say count ();
- say count ();
- say count ();
- #say $counter;
In this example, instead of using my to declare the internal variable , we used the state keyword.
$counter is initialized to 0 only once, the first time we call counter() . In subsequent calls, the line state $counter = 0; does not get executed and $counter has the same value as it had when we left the function the last time.Thus the output will be:
1 2 3If we removed the # from last line, it would generate a Global symbol "$counter" requires explicit package name at ... line ... error when trying to compile the script. This just shows that the variable $counter is not accessible outside the function.
state is executed in the first callCheck out this strange example:
- use strict ;
- use warnings ;
- use 5.010 ;
- sub count {
- state $counter = say "world" ;
- $counter ++;
- return $counter ;
- }
- say "hello" ;
- say count ();
- say count ();
- say count ();
This will print out
hello world 2 3 4showing that the state $counter = say "world"; line only gets executed once. In the first call to count() say , which was also added in version 5.10 , will return 1 upon success.
static variables in the "traditional" way
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my $counter = 0 ;
- sub count {
- $counter ++;
- return $counter ;
- }
- }
- say count ();
- say count ();
- say count ();
This provides the same result as the above version using state , except that this could work in older versions of perl as well. (Especially if I did not want to use the say keyword, that was also introduced in 5.10.)
This version works because functions declarations are global in perl - so count() is accessible in the main body of the script even though it was declared inside a block. On the other hand the variable $counter is not accessible from the outside world because it was declared inside the block. Lastly, but probably most importantly, it does not get destroyed when we leave the count() function (or when the execution is outside the block), because the existing count() function still references it.
Thus $count is effectively a static variable.
First assignment time
- use strict ;
- use warnings ;
- use 5.010 ;
- say "hi" ;
- {
- my $counter = say "world" ;
- sub count {
- $counter ++;
- return $counter ;
- }
- }
- say "hello" ;
- say count ();
- say count ();
- say count ();
hi world hello 2 3 4This shows that in this case too, the declaration and the initial assignment my $counter = say "world"; happens only once, but we can also see that the assignment happens before the first call to count() as if the my $counter = say "world"; statement was part of the control flow of the code outside of the block.
Shared static variableThis "traditional" or "home made" static variable has an extra feature. Because it does not belong to the the count() subroutine, but to the block surrounding it, we can declare more than one functions in that block and we can share this static variable between two or even more functions.
For example we could add a reset_counter() function:
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my $counter = 0 ;
- sub count {
- $counter ++;
- return $counter ;
- }
- sub reset_counter {
- $counter = 0 ;
- }
- }
- say count ();
- say count ();
- say count ();
- reset_counter ();
- say count ();
- say count ();
1 2 3 1 2Now both functions can access the $counter variable, but still nothing outside the enclosing block can access it.
Static arrays and hashesAs of now, you cannot use the state declaration in list context. This means you cannot write state @y = (1, 1); . This limitation could be overcome by some extra coding. For example in this implementation of the Fibonacci series, we checked if the array is empty and set the default values:
- use strict ;
- use warnings ;
- use 5.010 ;
- sub fib {
- state @y ;
- @y = ( 1 , 1 ) if not @y ; # workaround initialization
- push @y , $y [ 0 ]+ $y [ 1 ];
- return shift @y ;
- }
- say fib ();
- say fib ();
- say fib ();
- say fib ();
- say fib ();
Alternatively we could use the "old-style" static variable with the enclosing block.
Here is the example generating the Fibonacci series:
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my @y = ( 1 , 1 );
- sub fib {
- push @y , $y [ 0 ]+ $y [ 1 ];
- return shift @y ;
- }
- }
- say fib ();
- say fib ();
- say fib ();
- say fib ();
- say fib ();
Oct 09, 2019 | perlmaven.com
use vars
The problem is that use strict is complaining that there is a variable $x which is not declared with my and that it does not know about it. So we need a way to tell strict that it is ok. We know about the $x variable and we want to use it, but we want it to be a package variable. We don't want to declare it using my and we don't want to always prefix it with the package name.
With use vars ('$x') we can achieve that:
- use strict ;
- package VeryLongName ;
- use vars ( '$x' );
- $x = 23 ;
- print "VeryLongName: $x\n" ;
This works, but the documentation of vars tells us that the functionality provided by this pragma has been superseded by "our" declarations .
So how does our work?
ourCaveat
- use strict ;
- package VeryLongName ;
- our $x = 23 ;
- print "VeryLongName: $x\n" ;
The our declaration itself is lexically scoped, meaning it is limited by the file or by enclosing curly braces. In the next example we don't have curly braces and thus the declaration our $x = 23; will be intact even after switching namespaces. This can lead to very unpleasant situations. My recommendation is to avoid using our (you almost always need to use my anyway) and to put every package in its own file.
- use strict ;
- package VeryLongName ;
- our $x = 23 ;
- print "VeryLongName: $x\n" ; # VeryLongName: 23
- package main ;
- print "$x\n" ; # 23
Oct 09, 2019 | stackoverflow.com
Asked 10 years, 5 months ago Active 3 years, 1 month ago Viewed 107k times 180 56
Nathan Fellman ,May 10, 2009 at 10:24
I know whatmy
is in Perl. It defines a variable that exists only in the scope of the block in which it is defined. What doesour
do? How doesour
differ frommy
?Nathan Fellman ,Nov 20, 2016 at 1:15
Great question: How doesour
differ frommy
and what doesour
do?In Summary:
Available since Perl 5,
my
is a way to declare:
- non-package variables, that are
- private,
- new ,
- non-global variables,
- separate from any package. So that the variable cannot be accessed in the form of
$package_name::variable
.
On the other hand,
our
variables are:
- package variables, and thus automatically
- global variables,
- definitely not private ,
- nor are they necessarily new; and they
- can be accessed outside the package (or lexical scope) with the qualified namespace, as
$package_name::variable
.
Declaring a variable with
our
allows you to predeclare variables in order to use them underuse strict
without getting typo warnings or compile-time errors. Since Perl 5.6, it has replaced the obsoleteuse vars
, which was only file-scoped, and not lexically scoped as isour
.For example, the formal, qualified name for variable
$x
insidepackage main
is$main::x
. Declaringour $x
allows you to use the bare$x
variable without penalty (i.e., without a resulting error), in the scope of the declaration, when the script usesuse strict
oruse strict "vars"
. The scope might be one, or two, or more packages, or one small block.Georg ,Oct 1, 2016 at 6:41
The PerlMonks and PerlDoc links from cartman and Olafur are a great reference - below is my crack at a summary:
my
variables are lexically scoped within a single block defined by{}
or within the same file if not in{}
s. They are not accessible from packages/subroutines defined outside of the same lexical scope / block.
our
variables are scoped within a package/file and accessible from any code thatuse
orrequire
that package/file - name conflicts are resolved between packages by prepending the appropriate namespace.Just to round it out,
local
variables are "dynamically" scoped, differing frommy
variables in that they are also accessible from subroutines called within the same block.Nathan Fellman ,Nov 20, 2015 at 18:46
An example:use strict; for (1 .. 2){ # Both variables are lexically scoped to the block. our ($o); # Belongs to 'main' package. my ($m); # Does not belong to a package. # The variables differ with respect to newness. $o ++; $m ++; print __PACKAGE__, " >> o=$o m=$m\n"; # $m is always 1. # The package has changed, but we still have direct, # unqualified access to both variables, because the # lexical scope has not changed. package Fubb; print __PACKAGE__, " >> o=$o m=$m\n"; } # The our() and my() variables differ with respect to privacy. # We can still access the variable declared with our(), provided # that we fully qualify its name, but the variable declared # with my() is unavailable. print __PACKAGE__, " >> main::o=$main::o\n"; # 2 print __PACKAGE__, " >> main::m=$main::m\n"; # Undefined. # Attempts to access the variables directly won't compile. # print __PACKAGE__, " >> o=$o\n"; # print __PACKAGE__, " >> m=$m\n"; # Variables declared with use vars() are like those declared # with our(): belong to a package; not private; and not new. # However, their scoping is package-based rather than lexical. for (1 .. 9){ use vars qw($uv); $uv ++; } # Even though we are outside the lexical scope where the # use vars() variable was declared, we have direct access # because the package has not changed. print __PACKAGE__, " >> uv=$uv\n"; # And we can access it from another package. package Bubb; print __PACKAGE__, " >> main::uv=$main::uv\n";daotoad ,May 10, 2009 at 16:37
Coping with Scoping is a good overview of Perl scoping rules. It's old enough thatour
is not discussed in the body of the text. It is addressed in the Notes section at the end.The article talks about package variables and dynamic scope and how that differs from lexical variables and lexical scope.
Chas. Owens ,Oct 7, 2013 at 14:02
my is used for local variables, where as our is used for global variables. More reading over Variable Scoping in Perl: the basics .ruffin ,Feb 10, 2015 at 19:47
It's an old question, but I ever met some pitfalls about lexical declarations in Perl that messed me up, which are also related to this question, so I just add my summary here:1. definition or declaration?
local $var = 42; print "var: $var\n";The output is
var: 42
. However we couldn't tell iflocal $var = 42;
is a definition or declaration. But how about this:use strict; use warnings; local $var = 42; print "var: $var\n";The second program will throw an error:
Global symbol "$var" requires explicit package name.
$var
is not defined, which meanslocal $var;
is just a declaration! Before usinglocal
to declare a variable, make sure that it is defined as a global variable previously.But why this won't fail?
use strict; use warnings; local $a = 42; print "var: $a\n";The output is:
var: 42
.That's because
$a
, as well as$b
, is a global variable pre-defined in Perl. Remember the sort function?2. lexical or global?
I was a C programmer before starting using Perl, so the concept of lexical and global variables seems straightforward to me: just corresponds to auto and external variables in C. But there're small differences:
In C, an external variable is a variable defined outside any function block. On the other hand, an automatic variable is a variable defined inside a function block. Like this:
int global; int main(void) { int local; }While in Perl, things are subtle:
sub main { $var = 42; } &main; print "var: $var\n";The output is
var: 42
,$var
is a global variable even it's defined in a function block! Actually in Perl, any variable is declared as global by default.The lesson is to always add
use strict; use warnings;
at the beginning of a Perl program, which will force the programmer to declare the lexical variable explicitly, so that we don't get messed up by some mistakes taken for granted.Ólafur Waage ,May 10, 2009 at 10:25
The perldoc has a good definition of our.Unlike my, which both allocates storage for a variable and associates a simple name with that storage for use within the current scope, our associates a simple name with a package variable in the current package, for use within the current scope. In other words, our has the same scoping rules as my, but does not necessarily create a variable.
Cosmicnet ,Nov 22, 2014 at 13:57
This is only somewhat related to the question, but I've just discovered a (to me) obscure bit of perl syntax that you can use with "our" (package) variables that you can't use with "my" (local) variables.#!/usr/bin/perl our $foo = "BAR"; print $foo . "\n"; ${"foo"} = "BAZ"; print $foo . "\n";Output:
BAR BAZThis won't work if you change 'our' to 'my'.
Okuma.Scott ,Sep 6, 2014 at 20:13
print "package is: " . __PACKAGE__ . "\n"; our $test = 1; print "trying to print global var from main package: $test\n"; package Changed; { my $test = 10; my $test1 = 11; print "trying to print local vars from a closed block: $test, $test1\n"; } &Check_global; sub Check_global { print "trying to print global var from a function: $test\n"; } print "package is: " . __PACKAGE__ . "\n"; print "trying to print global var outside the func and from \"Changed\" package: $test\n"; print "trying to print local var outside the block $test1\n";Will Output this:
package is: main trying to print global var from main package: 1 trying to print local vars from a closed block: 10, 11 trying to print global var from a function: 1 package is: Changed trying to print global var outside the func and from "Changed" package: 1 trying to print local var outside the blockIn case using "use strict" will get this failure while attempting to run the script:
Global symbol "$test1" requires explicit package name at ./check_global.pl line 24. Execution of ./check_global.pl aborted due to compilation errors.Nathan Fellman ,Nov 5, 2015 at 14:03
Just try to use the following program :#!/usr/local/bin/perl use feature ':5.10'; #use warnings; package a; { my $b = 100; our $a = 10; print "$a \n"; print "$b \n"; } package b; #my $b = 200; #our $a = 20 ; print "in package b value of my b $a::b \n"; print "in package b value of our a $a::a \n";Nathan Fellman ,May 16, 2013 at 11:07
#!/usr/bin/perl -l use strict; # if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee' #my $lol = 'eeeeeeeeeee' ; # no errors or warnings at any case, despite of 'strict' our $lol = eval {$lol} || 'lol' ; print $lol;Evgeniy ,Jan 27, 2016 at 4:57
Let us think what an interpreter actually is: it's a piece of code that stores values in memory and lets the instructions in a program that it interprets access those values by their names, which are specified inside these instructions. So, the big job of an interpreter is to shape the rules of how we should use the names in those instructions to access the values that the interpreter stores.On encountering "my", the interpreter creates a lexical variable: a named value that the interpreter can access only while it executes a block, and only from within that syntactic block. On encountering "our", the interpreter makes a lexical alias of a package variable: it binds a name, which the interpreter is supposed from then on to process as a lexical variable's name, until the block is finished, to the value of the package variable with the same name.
The effect is that you can then pretend that you're using a lexical variable and bypass the rules of 'use strict' on full qualification of package variables. Since the interpreter automatically creates package variables when they are first used, the side effect of using "our" may also be that the interpreter creates a package variable as well. In this case, two things are created: a package variable, which the interpreter can access from everywhere, provided it's properly designated as requested by 'use strict' (prepended with the name of its package and two colons), and its lexical alias.
Sources:
Oct 08, 2019 | stackoverflow.com
Ask Question Asked 6 years, 1 month ago Active 4 years ago Viewed 5k times 4 1
Alec ,Sep 5, 2018 at 8:25
use constant { COLUMNS => qw/ TEST1 TEST2 TEST3 /, }Can I store an array using the constant package in Perl?
Whenever I go on to try to use the array like
my @attr = (COLUMNS);
, it does not contain the values.Сухой27 ,Aug 12, 2013 at 13:37
use constant { COLUMNS => [qw/ TEST1 TEST2 TEST3 /], }; print @{+COLUMNS};> ,
Or remove the curly braces as the docs show :-1 use strict; 2 use constant COLUMNS => qw/ TEST1 TEST2 TEST3 /; 3 4 my @attr = (COLUMNS); 5 print @attr;which gives :-
% perl test.pl TEST1TEST2TEST3Your code actually defines two constants COLUMNS and TEST2 :-
use strict; use constant { COLUMNS => qw/ TEST1 TEST2 TEST3 /, }; my @attr = (COLUMNS); print @attr; print TEST2and gives :-
% perl test.pl TEST1TEST3
Sep 10, 2019 | perlmaven.com
Prev Next This is one of the most common warning you will encounter while running Perl code.It is a warning, it won't stop your script from running and it is only generated if warnings were turned on. Which is recommended.
The most common way to turn on warnings is by including a use warnings; statement at the beginning of your script or module.
Are you serious about Perl? Check out my Beginner Perl Maven book .
I have written it for you!The older way is adding a -w flag on the sh-bang line. Usually looks like this as the first line of your script:
#!/usr/bin/perl -w
There are certain differences, but as use warnings is available for 12 years now, there is no reason to avoid it. In other words:
Always use warnings; !
Let's go back to the actual warning I wanted to explain.
A quick explanationUse of uninitialized value $x in say at perl_warning_1.pl line 6.This means the variable $x has no value (its value is the special value undef ). Either it never got a value, or at some point undef was assigned to it.
You should look for the places where the variable got the last assignment, or you should try to understand why that piece of code has never been executed.
A simple exampleThe following example will generate such warning.
- use warnings ;
- use strict ;
- use 5.010 ;
- my $x ;
- say $x ;
Perl is very nice, tells us which file generated the warning and on which line.
Only a warningAs I mentioned this is only a warning. If the script has more statements after that say statement, they will be executed:
- use warnings ;
- use strict ;
- use 5.010 ;
- my $x ;
- say $x ;
- $x = 42 ;
- say $x ;
This will print
Use of uninitialized value $x in say at perl_warning_1.pl line 6. 42Confusing output orderBeware though, if your code has print statements before the line generating the warning, like in this example:
- use warnings ;
- use strict ;
- use 5.010 ;
- print 'OK' ;
- my $x ;
- say $x ;
- $x = 42 ;
- say $x ;
the result might be confusing.
Use of uninitialized value $x in say at perl_warning_1.pl line 7. OK 42Here, 'OK', the result of the print is seen after the warning, even though it was called before the code that generated the warning.
This strangeness is the result of IO buffering . By default Perl buffers STDOUT, the standard output channel, while it does not buffer STDERR, the standard error channel.
So while the word 'OK' is waiting for the buffer to be flushed, the warning message already arrives to the screen.
Turning off bufferingIn order to avoid this you can turn off the buffering of STDOUT.
This is done by the following code: $| = 1; at the beginning of the script.
- use warnings ;
- use strict ;
- use 5.010 ;
- $ | = 1 ;
- print 'OK' ;
- my $x ;
- say $x ;
- $x = 42 ;
- say $x ;
OKUse of uninitialized value $x in say at perl_warning_1.pl line 7. 42(The warning is on the same line as the OK because we have not printed a newline \n after the OK.)
The unwanted scope
- use warnings ;
- use strict ;
- use 5.010 ;
- my $x ;
- my $y = 1 ;
- if ( $y ) {
- my $x = 42 ;
- }
- say $x ;
This code too produces Use of uninitialized value $x in say at perl_warning_1.pl line 11.
I have managed to make this mistake several times. Not paying attention I used my $x inside the if block, which meant I have created another $x variable, assigned 42 to it just to let it go out of the scope at the end of the block. (The $y = 1 is just a placeholder for some real code and some real condition. It is there only to make this example a bit more realistic.)
There are of course cases when I need to declare a variable inside an if block, but not always. When I do that by mistake it is painful to find the bug.
Sep 10, 2019 | stackoverflow.com
marto ,Jul 15, 2011 at 16:52
I use thisscrub
function to clean up output from other functions.#!/usr/bin/perl use warnings; use strict; use Data::Dumper; my %h = ( a => 1, b => 1 ); print scrub($h{c}); sub scrub { my $a = shift; return ($a eq '' or $a eq '~' or not defined $a) ? -1 : $a; }The problem occurs when I also would like to handle the case, where the key in a hash doesn't exist, which is shown in the example with
scrub($h{c})
.What change should be make to
scrub
so it can handle this case?Sandra Schlichting ,Jun 22, 2017 at 19:00
You're checking whether$a eq ''
before checking whether it's defined, hence the warning "Use of uninitialized value in string eq". Simply change the order of things in the conditional:return (!defined($a) or $a eq '' or $a eq '~') ? -1 : $a;As soon as anything in the chain of 'or's matches, Perl will stop processing the conditional, thus avoiding the erroneous attempt to compare undef to a string.
Sandra Schlichting ,Jul 14, 2011 at 14:34
Inscrub
it is too late to check, if the hash has an entry for keykey
.scrub()
only sees a scalar, which isundef
, if the hash key does not exist. But a hash could have an entry with the valueundef
also, like this:my %h = ( a => 1, b => 1, c => undef );So I suggest to check for hash entries with the
exists
function.
Sep 10, 2019 | stackoverflow.com
How do I check if a Perl scalar variable has been initialized? Ask Question Asked 8 years, 11 months ago Active 3 years ago Viewed 49k times 33 10
brian d foy ,Sep 18, 2010 at 13:53
Is the following the best way to check if a scalar variable is initialized in Perl, usingdefined
?my $var; if (cond) { $var = "string1"; } # Is this the correct way? if (defined $var) { ... }mob ,Sep 25, 2010 at 21:35
Perl doesn't offer a way to check whether or not a variable has been initialized.However, scalar variables that haven't been explicitly initialized with some value happen to have the value of
undef
by default. You are right aboutdefined
being the right way to check whether or not a variable has a value ofundef
.There's several other ways tho. If you want to assign to the variable if it's
undef
, which your example code seems to indicate, you could, for example, use perl's defined-or operator:$var //= 'a default value';vol7ron ,Sep 17, 2010 at 23:17
It depends on what you're trying to do. The properC
way to do things is to initialize variables when they are declared; however,Perl is not C
, so one of the following may be what you want:1) $var = "foo" unless defined $var; # set default after the fact 2) $var = defined $var? $var : {...}; # ternary operation 3) {...} if !(defined $var); # another way to write 1) 4) $var = $var || "foo"; # set to $var unless it's falsy, in which case set to 'foo' 5) $var ||= "foo"; # retain value of $var unless it's falsy, in which case set to 'foo' (same as previous line) 6) $var = $var // "foo"; # set to $var unless it's undefined, in which case set to 'foo' 7) $var //= "foo"; # 5.10+ ; retain value of $var unless it's undefined, in which case set to 'foo' (same as previous line)
C way of doing things ( not recommended ):# initialize the variable to a default value during declaration # then test against that value when you want to see if it's been changed my $var = "foo"; {...} if ($var eq "foo"){ ... # do something } else { ... # do something else }Another long-winded way of doing this is to create a class and a flag when the variable's been changed, which is unnecessary.
Axeman ,Sep 17, 2010 at 20:39
If you don't care whether or not it's empty, it is. Otherwise you can checkif ( length( $str || '' )) {}swilliams ,Sep 17, 2010 at 20:53
It depends on what you plan on doing with the variable whether or not it is defined; as of Perl 5.10, you can do this (from perl51000delta ):A new operator // (defined-or) has been implemented. The following expression:
$a // $bis merely equivalent to
defined $a ? $a : $band the statement
$c //= $d;can now be used instead of
$c = $d unless defined $c;rafl ,Jun 24, 2012 at 7:53
'defined' will return true if a variable has a real value.As an aside, in a hash, this can be true:
if(exists $h{$e} && !defined $h{$e})
Aug 26, 2019 | perlmaven.com
In most of the cases we either want a variable to be accessible only from inside a small scope, inside a function or even inside a loop. These variables get created when we enter the function (or the scope created by a a block) and destroyed when we leave the scope.
In some cases, especially when we don't want to pay attention to our code, we want variables to be global, to be accessible from anywhere in our script and be destroyed only when the script ends. In General having such global variables is not a good practice.
In some cases we want a variable to stay alive between function calls, but still to be private to that function. We want it to retain its value between calls.
Are you serious about Perl? Check out my Beginner Perl Maven book .
I have written it for you!In the C programming language one can designate a variable to be a static variable . This means it gets initialized only once and it sticks around retaining its old value between function calls.
In Perl, the same can be achieved using the state variable which is available starting from version 5.10, but there is a construct that will work in every version of Perl 5. In a way it is even more powerful.
Let's create a counter as an example:
state variable
- use strict ;
- use warnings ;
- use 5.010 ;
- sub count {
- state $counter = 0 ;
- $counter ++;
- return $counter ;
- }
- say count ();
- say count ();
- say count ();
- #say $counter;
In this example, instead of using my to declare the internal variable , we used the state keyword.
$counter is initialized to 0 only once, the first time we call counter() . In subsequent calls, the line state $counter = 0; does not get executed and $counter has the same value as it had when we left the function the last time.Thus the output will be:
1 2 3If we removed the # from last line, it would generate a Global symbol "$counter" requires explicit package name at ... line ... error when trying to compile the script. This just shows that the variable $counter is not accessible outside the function.
state is executed in the first callCheck out this strange example:
- use strict ;
- use warnings ;
- use 5.010 ;
- sub count {
- state $counter = say "world" ;
- $counter ++;
- return $counter ;
- }
- say "hello" ;
- say count ();
- say count ();
- say count ();
This will print out
hello world 2 3 4showing that the state $counter = say "world"; line only gets executed once. In the first call to count() say , which was also added in version 5.10 , will return 1 upon success.
static variables in the "traditional" way
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my $counter = 0 ;
- sub count {
- $counter ++;
- return $counter ;
- }
- }
- say count ();
- say count ();
- say count ();
This provides the same result as the above version using state , except that this could work in older versions of perl as well. (Especially if I did not want to use the say keyword, that was also introduced in 5.10.)
This version works because functions declarations are global in perl - so count() is accessible in the main body of the script even though it was declared inside a block. On the other hand the variable $counter is not accessible from the outside world because it was declared inside the block. Lastly, but probably most importantly, it does not get destroyed when we leave the count() function (or when the execution is outside the block), because the existing count() function still references it.
Thus $count is effectively a static variable.
First assignment time
- use strict ;
- use warnings ;
- use 5.010 ;
- say "hi" ;
- {
- my $counter = say "world" ;
- sub count {
- $counter ++;
- return $counter ;
- }
- }
- say "hello" ;
- say count ();
- say count ();
- say count ();
hi world hello 2 3 4This shows that in this case too, the declaration and the initial assignment my $counter = say "world"; happens only once, but we can also see that the assignment happens before the first call to count() as if the my $counter = say "world"; statement was part of the control flow of the code outside of the block.
Shared static variableThis "traditional" or "home made" static variable has an extra feature. Because it does not belong to the the count() subroutine, but to the block surrounding it, we can declare more than one functions in that block and we can share this static variable between two or even more functions.
For example we could add a reset_counter() function:
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my $counter = 0 ;
- sub count {
- $counter ++;
- return $counter ;
- }
- sub reset_counter {
- $counter = 0 ;
- }
- }
- say count ();
- say count ();
- say count ();
- reset_counter ();
- say count ();
- say count ();
1 2 3 1 2Now both functions can access the $counter variable, but still nothing outside the enclosing block can access it.
Static arrays and hashesAs of now, you cannot use the state declaration in list context. This means you cannot write state @y = (1, 1); . This limitation could be overcome by some extra coding. For example in this implementation of the Fibonacci series, we checked if the array is empty and set the default values:
- use strict ;
- use warnings ;
- use 5.010 ;
- sub fib {
- state @y ;
- @y = ( 1 , 1 ) if not @y ; # workaround initialization
- push @y , $y [ 0 ]+ $y [ 1 ];
- return shift @y ;
- }
- say fib ();
- say fib ();
- say fib ();
- say fib ();
- say fib ();
Alternatively we could use the "old-style" static variable with the enclosing block.
Here is the example generating the Fibonacci series:
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my @y = ( 1 , 1 );
- sub fib {
- push @y , $y [ 0 ]+ $y [ 1 ];
- return shift @y ;
- }
- }
- say fib ();
- say fib ();
- say fib ();
- say fib ();
Google matched content |
...
Society
Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers : Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism : The Iron Law of Oligarchy : Libertarian Philosophy
Quotes
War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda : SE quotes : Language Design and Programming Quotes : Random IT-related quotes : Somerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose Bierce : Bernard Shaw : Mark Twain Quotes
Bulletin:
Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 : Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law
History:
Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds : Larry Wall : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOS : Programming Languages History : PL/1 : Simula 67 : C : History of GCC development : Scripting Languages : Perl history : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history
Classic books:
The Peter Principle : Parkinson Law : 1984 : The Mythical Man-Month : How to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite
Most popular humor pages:
Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor
The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D
Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.
FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.
This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...
|
You can use PayPal to to buy a cup of coffee for authors of this site |
Disclaimer:
The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.
Last modified: November, 22, 2020