I quite like glob's often overlooked iterator-esque functionality.
What's not clear to me is whether it computes/loads the entire list into memory even when used in scalar context. In this example code, the while loop does not print anything to screen (4**24 is not a small number):
use strict;
use warnings;
use feature 'say';
my $opt = "{A,B,C,D}" x 24;
say while glob $opt;
Things I've tried/observed:
I tried to eliminate the possibility of buffering being an issue by writing 1 while glob $opt;, but it still takes forever and I end up Ctrl+C'ing out.
Inspection of my memory usage via Windows Task Manager doesn't seem to show any difference when I run the script.
Running perl -MO=Deparse only confirms that glob is being used in scalar context without indicating anything about memory usage.
Running perl -MO=Concise results in the following output, which I don't know how to decipher:
m <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 49 -:5) v:%,*,&,{,x*,x&,x$,$,469762048 ->3
7 <2> sassign vKS/2 ->8
5 <2> repeat[t2] sK/2 ->6
3 <$> const[PV "{A,B,C,D}"] s ->4
4 <$> const[IV 24] s ->5
6 <0> padsv[$opt:49,74] sRM*/LVINTRO ->7
8 <;> nextstate(main 74 -:6) v:%,*,&,{,x*,x&,x$,$,469762048 ->9
l <@> leave vK* ->m
9 <0> enter v ->a
- <1> null vKP/1 ->l
g <|> and(other->h) vK/1 ->l
f <1> defined sK/1 ->g
e <2> sassign sK/2 ->f
c <@> glob[t5] sK/1 ->d
- <0> ex-pushmark s ->a
a <0> padsv[$opt:49,74] s ->b
b <#> gv[*_GEN_0] s ->c
- <1> ex-rv2sv sKRM*/3 ->e
d <#> gvsv[*_] s ->e
- <@> lineseq vK ->-
j <@> say vK ->k
h <0> pushmark s ->i
- <1> ex-rv2sv sK/3 ->j
i <#> gvsv[*_] s ->j
k <0> unstack v ->a
- syntax OK
I'm running ActivePerl 5.16.3.
It does not appear to be lazy when you observe a delay between first glob invocation and first print of the result. This is further corroborated by the time it takes to execute a glob in the scalar context not in a loop (in my example I used smaller exponent so that delay is still noticeable but not too long):
use strict;
use warnings;
use feature 'say';
use Time::HiRes;
$| = 1;
my $opt = "{A,B,C,D}" x 10;
say Time::HiRes::time;
my $x = glob $opt;
say $x;
say Time::HiRes::time;
say while glob $opt;
say Time::HiRes::time;
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