perl -MO=Concise -e 'for(1 .. 100){print if $_ < 50}' perl -MO=Concise -e 'for(grep $_ < 50, (1 .. 100)){print}' You'll notice that you've just traded an "and" and a few constants for that larger grep. leaveloop enteriter pushmark - const - const + grepwhile + grepstart + pushmark + lt + gvsv + const + rv2av + const gv and iter lineseq nextstate - and - lt - gvsv - const - print - pushmark - gvsv + print + pushmark + gvsv unstack nextstate perl -MO=Concise -e '$array_ref=[1..10000];for(@$array_ref){print}' perl -MO=Concise -e '$array_ref=[1..10000];for($i=0;$_=$array_ref->[$i];$i++){print}' Here you'll notice that you you doubled the number of operations being performed for handling the first construct. Ugly. nextstate - leaveloop - enteriter - pushmark - rv2av - rv2sv - gv - gv - and - iter - lineseq - nextstate - print - pushmark + sassign + const + gvsv + lineseq + nextstate + leaveloop + enterloop + and + sassign + aelem + rv2av + rv2sv + gv + gvsv gvsv - unstack - nextstate + lineseq + scope + print + pushmark + gvsv + preinc + gvsv + unstack + nextstate