Details for the stateful behaviour for operators such as match (ie. m//g
), stat (ie. stat _
) and range (ie. //..//
) are in the documentation. However is there a 'listing' of all operators or functions that exhibit stateful behaviour? The ones that come to mind are:
#ARGV/File/dir/glob: The current line/position is remembered
say while <>; #Read line by line by Line from ARGV files
say while <$fh>; #Read line by line by line from file handle
say while defined($_ = readdir($dh)); #Read an entry at a time from dir handle
say while <*>; #Read an entry at a time from file glob in current dir
say while <{a,b,c},{1,2}>; #Print combination glob one at a time ie (a1,b1,c1,a2,b2,c2)
#Regex: Global modifier/list context remembers previous matches
say while m/$re/g; #Print matches one at a time
my $_="hello"; say /hello/g; say /hello/gc; #Only prints hello once. Stateful continuation from last match position
#stat
stat _; #Returns stat array state from previous stat "filename";
#range: State remembers if the first condition is met
perl -n -e 'print if 1..10' myfile.txt; #Bistable flipflop state. Print lines 1 to 10
perl -n -e 'print if /startmatch/../endmatch/' myfile.text; #print lines between matches
#state variable: make your own
sub { state $myStateVar;}; #Your own state variable
Any info would be great. Thanks
There are three stateful operators.
glob
in scalar context (including <>
used as glob
).
for my $pass (1..2) {
say glob("abc") // "[undef]";
}
Output
abc
[undef]
The flip-flop operator (..
and ...
in scalar context).
for my $pass (1..2) {
$. = 5;
say scalar(5..6);
}
Output
1
2
state
for my $pass (1..2) {
state $x = "abc";
say $x;
$x = "def";
}
Output
abc
def
A lot of operators use the TARG
mechanism which makes them technically stateful, but this is an optimization that's transparent to the user. The mechanism allows operators to remember the scalar they return so it can be reused by subsequent invocations.
perl -e'
use Devel::Peek qw( Dump );
for my $pass (1..2) {
my $x = "abc";
Dump(uc($x));
}
' 2>&1 | grep -P '^SV ='
Output
SV = PV(0x55d87231fea0) at 0x55d87237ce08
SV = PV(0x55d87231fea0) at 0x55d87237ce08
It's not a coincidence that both scalars are at the same address (0x55d87237ce08
); it's the same scalar.
It was suggested that m//g
in scalar context is stateful, but its result is strictly based on its inputs. The effect observed is the result of using pos($_)
, where $_
is an input.
local $_ = "abcdef";
for my $pass (1..2) {
pos($_) = 2;
last if !/./g;
say $&;
}
Output
c
c
It was suggested that each
is stateful, but its result is strictly based on its input. The effect observed is the result of using an iterator that's part of the input.
my %h = ( a=>1, b=>2, c=>3 );
for my $pass (1..2) {
keys(%h); # `keys` in void context resets a hash's iterator.
say join " ", each(%h);
}
Output
c 3
c 3
keys
and values
also use this same iterator.
It was suggested that readline
and readdir
are stateful, but their result is strictly based on their input. The only reason you were getting different outputs is that the input (the file handle or directory handle) was different each time.
These functions (and many others) have side effects, and these side-effects including modifying their inputs. But I wouldn't call them stateful as there are significant differences between these and stateful operators.
stat
is stateful, but its result is strictly based on its input (be it _
or something else).This one is not the least bit stateful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With