4.4. Loop Statements - Programming Perl, 3rd Edition [Book]

文章推薦指數: 80 %
投票人數:10人

The while or until statement can have an optional extra block: the continue block. This block is executed every time the block is continued, either by ... Skiptomaincontent ProgrammingPerl,3rdEditionby GetfullaccesstoProgrammingPerl,3rdEditionand60K+othertitles,withfree10-daytrialofO'Reilly. There'salsoliveonlineevents,interactivecontent,certificationprepmaterials,andmore. Startyourfreetrial LoopStatementsAllloopstatementshaveanoptional LABELintheirformalsyntax.(Youcanput alabelonanystatement,butithasaspecialmeaningtoaloop.)If present,thelabelconsistsofanidentifierfollowedbyacolon.It's customarytomakethelabeluppercasetoavoidpotentialconfusion withreservedwords,andsoitstandsoutbetter.AndalthoughPerl won'tgetconfusedifyouusealabelthatalreadyhasameaninglike iforopen,yourreadersmight. whileanduntilStatementsThewhilestatementrepeatedly executestheblockaslongasEXPRis true.Ifthewordwhileisreplacedbytheword until,thesenseofthetestisreversed;that is,itexecutestheblockonlyaslongas EXPRremainsfalse.Theconditionalis stilltestedbeforethefirstiteration,though.Thewhileor untilstatementcanhaveanoptionalextrablock: thecontinueblock.Thisblockisexecutedevery timetheblockiscontinued,eitherbyfallingofftheendofthe firstblockorbyanexplicitnext(a loop-controloperatorthatgoestothenextiteration).The continueblockisnotheavilyusedinpractice, butit'sinheresowecandefinetheforloop rigorouslyinthenextsection.Unliketheforeachloopwe'llseeina moment,awhileloopneverimplicitlylocalizes anyvariablesinitstestcondition.Thiscanhave"interesting" consequenceswhenwhileloopsuseglobalsfor loopvariables.Inparticular,seeSection2.11.2inChapter2forhowimplicitassignment totheglobal$_canoccurincertain whileloops,alongwithanexampleofhowtodeal withtheproblembyexplicitlylocalizing$_.For otherloopvariables,however,it'sbesttodeclarethemwith my,asinthenextexample.Avariabledeclaredinthetestconditionofa whileoruntilstatementis visibleonlyintheblockorblocksgovernedbythattest.Itisnot partofthesurroundingscope.Forexample:while(my$line=){ $line=lc$line; } continue{ print$line;#stillvisible } #$linenowoutofscopehereHerethescopeof$lineextendsfromits declarationinthecontrolexpressionthroughouttherestofthe loopconstruct,includingthecontinueblock,but notbeyond.Ifyouwantthescopetoextendfurther,declarethe variablebeforetheloop.forLoopsThethree-partforloophasthree semicolon-separatedexpressionswithinitsparentheses.These expressionsfunctionrespectivelyastheinitialization,the condition,andthere-initializationexpressionsoftheloop.All threeexpressionsareoptional(butnotthesemicolons);ifomitted, theconditionisalwaystrue.Thus,thethree-part forloopcanbedefinedintermsofthe correspondingwhileloop.This:LABEL: for(my$i=1;$i<=10;$i++){ … }islikethis:{ my$i=1; LABEL: while($i<=10){ … }continue{ $i++; } }exceptthatthere'snotreallyanouterblock.(Wejustput onetheretoshowhowthescopeofthemyis limited.)Ifyouwanttoiteratethroughtwovariables simultaneously,justseparatetheparallelexpressionswith commas:for($i=0,$bit=0;$i<32;$i++,$bit<<=1){ print"Bit$iisset\n"if$mask&$bit; } #thevaluesin$iand$bitpersistpasttheloopOrdeclarethosevariablestobevisibleonlyinsidethe forloop:for(my($i,$bit)=(0,1);$i<32;$i++,$bit<<=1){ print"Bit$iisset\n"if$mask&$bit; } #loop'sversionsof$iand$bitnowoutofscopeBesidesthenormalloopingthrougharrayindices, forcanlenditselftomanyotherinteresting applications.Itdoesn'tevenneedanexplicitloopvariable.Here's oneexamplethatavoidstheproblemyougetwhenyouexplicitlytest forend-of-fileonaninteractivefiledescriptor,causingyour programtoappeartohang.$on_a_tty=-tSTDIN&&-tSTDOUT; subprompt{print"yes?"if$on_a_tty} for(prompt();;prompt()){ #dosomething }Anothertraditionalapplicationforthethree-part forloopresultsfromthefactthatallthree expressionsareoptional,andthedefaultconditionistrue.Ifyou leaveoutallthreeexpressions,youhavewrittenaninfinite loop:for(;;){ … }Thisisthesameaswriting:while(1){ … }Ifthenotionofinfiniteloopsbothersyou,we shouldpointoutthatyoucanalwaysfalloutoftheloopatany pointwithanexplicitloop-controloperatorsuchas last.Ofcourse,ifyou'rewritingthecodeto controlacruisemissile,youmaynotactuallyneedanexplicitloop exit.Theloopwillbeterminatedautomaticallyattheappropriate moment.[3]foreachLoopsTheforeachloopiteratesovera listofvaluesbysettingthecontrolvariable (VAR)toeachsuccessiveelementofthe list:foreachVAR(LIST){ … }Theforeachkeywordisjusta synonymfortheforkeyword,soyoucanuse foreachandfor interchangeably,whicheveryouthinkismorereadableinagiven situation.IfVARisomitted,theglobal $_isused.(Don'tworry--Perlcaneasily distinguishfor(@ARGV)fromfor($i=0; $i$hash{$key}\n"; }Thatlastoneisthecanonicalwaytoprintoutthevaluesof ahashinsortedorder.Seethekeysand sortentriesinChapter29formoreelaborate examples.Thereisnowaywithforeachtotellwhere youareinalist.Youmaycompareadjacentelementsbyremembering thepreviousoneinavariable,butsometimesyoujusthavetobreak downandwriteathree-partforloopwith subscripts.That'swhattheotherkindoffor loopistherefor,afterall.IfLISTconsistsentirely ofassignablevalues(meaningvariables,generally,notenumerated constants),youcanmodifyeachofthosevariablesbymodifying VARinsidetheloop.That'sbecausethe foreachloopindexvariableisanimplicitalias foreachiteminthelistthatyou'reloopingover.Notonlycanyou modifyasinglearrayinplace,youcanalsomodifymultiplearrays andhashesinasinglelist:foreach$pay(@salaries){#grant8%raises $pay*=1.08; } for(@christmas,@easter){#changemenu s/ham/turkey/; } s/ham/turkey/for@christmas,@easter;#samething for($scalar,@array,values%hash){ s/^\s+//;#stripleadingwhitespace s/\s+$//;#striptrailingwhitespace }Theloopvariableisvalidonlyfromwithinthedynamicor lexicalscopeoftheloopandwillbeimplicitlylexicalifthe variablewaspreviouslydeclaredwithmy.This rendersitinvisibletoanyfunctiondefinedoutsidethelexical scopeofthevariable,evenifcalledfromwithinthatloop. However,ifnolexicaldeclarationisinscope,theloopvariable willbealocalized(dynamicallyscoped)globalvariable;this allowsfunctionscalledfromwithinthelooptoaccessthat variable.Ineithercase,anypreviousvaluethelocalizedvariable hadbeforetheloopwillberestoredautomaticallyuponloop exit.Ifyouprefer,youmayexplicitlydeclarewhichkindof variable(lexicalorglobal)touse.Thismakesiteasierfor maintainersofyourcodetoknowwhat'sreallygoingon;otherwise, they'llneedtosearchbackupthroughenclosingscopesfora previousdeclarationtofigureoutwhichkindofvariableit is:formy$i(1..10){…}#$ialwayslexical forour$Tick(1..10){…}#$TickalwaysglobalWhenadeclarationaccompaniestheloopvariable,theshorter forspellingispreferredover foreach,sinceitreadsbetterinEnglish.Here'showaCorJavaprogrammermightfirstthinktocodeup aparticularalgorithminPerl:for($i=0;$i$ary2[$j]){ last;#Can'tgotoouterloop.:-( } $ary1[$i]+=$ary2[$j]; } #thisiswherethatlasttakesme }Buthere'showaveteranPerlprogrammermightdoit:WID:foreach$this(@ary1){ JET:foreach$that(@ary2){ nextWIDif$this>$that; $this+=$that; } }SeehowmucheasierthatwasinidiomaticPerl?It'scleaner, safer,andfaster.It'scleanerbecauseit'slessnoisy.It'ssafer becauseifcodegetsaddedbetweentheinnerandouterloopslater on,thenewcodewon'tbeaccidentallyexecuted,since next(explainedbelow)explicitlyiteratesthe outerloopratherthanmerelybreakingoutoftheinnerone.And it'sfasterbecausePerlexecutesaforeach statementmorerapidlythanitwouldtheequivalent forloop,sincetheelementsareaccessed directlyinsteadofthroughsubscripting.Butwriteithoweveryoulike.TMTOWTDI.Likethewhilestatement,the foreachstatementcanalsotakea continueblock.Thisletsyouexecuteabitof codeatthebottomofeachloopiterationnomatterwhetheryougot thereinthenormalcourseofeventsorthrougha next.Speakingofwhich,nowwecanfinallysayit: nextisnext.LoopControlWementionedthatyoucanputa LABELonalooptogiveitaname.The loop'sLABELidentifiestheloopforthe loop-controloperatorsnext, last,andredo.The LABELnamestheloopasawhole,notjust thetopoftheloop.Hence,aloop-controloperatorreferringtothe loopdoesn'tactually"goto"thelooplabelitself.Asfarasthe computerisconcerned,thelabelcouldjustaseasilyhavebeen placedattheendoftheloop.Butpeoplelikethingslabeledatthe top,forsomereason.Loopsaretypicallynamedfortheitemtheloopisprocessing oneachiteration.Thisinteractsnicelywiththeloop-control operators,whicharedesignedtoreadlikeEnglishwhenusedwithan appropriatelabelandastatementmodifier.Thearchetypalloop worksonlines,sothearchetypallooplabelis LINE:,andthearchetypalloop-controloperator issomethinglikethis:nextLINEif/^#/;#discardcommentsThesyntaxfortheloop-controloperatorsis:lastLABEL nextLABEL redoLABELTheLABELisoptional;ifomitted, theoperatorreferstotheinnermostenclosingloop.Butifyouwant tojumppastmorethanonelevel,youmustusea LABELtonametheloopyouwantto affect.ThatLABELdoesnothavetobein yourlexicalscope,thoughitprobablyoughttobe.Butinfact,the LABELcanbeanywhereinyourdynamic scope.Ifthisforcesyoutojumpoutofaneval orsubroutine,Perlissuesawarning(uponrequest).Justasyoumayhaveasmany returnoperatorsinafunctionasyoulike,you mayhaveasmanyloop-controloperatorsinaloopasyoulike.This isnottobeconsideredwickedorevenuncool.Duringtheearlydays ofstructuredprogramming,somepeopleinsistedthatloopsand subroutineshaveonlyoneentryandoneexit.Theone-entrynotion isstillagoodidea,buttheone-exitnotionhasledpeopleto writealotofunnaturalcode.Muchofprogrammingconsistsof traversingdecisiontrees.Adecisiontreenaturallystartswitha singletrunkbutendswithmanyleaves.Writeyourcodewiththe numberofloopexits(andfunctionreturns)thatisnaturaltothe problemyou'retryingtosolve.Ifyou'vedeclaredyourvariables withreasonablescopes,everythinggetsautomaticallycleanedupat theappropriatemoment,nomatterhowyouleavetheblock.Thelastoperatorimmediately exitstheloopinquestion.Thecontinueblock, ifany,isnotexecuted.Thefollowingexamplebombsoutoftheloop onthefirstblankline:LINE:while(){ lastLINEif/^$/;#exitwhendonewithmailheader … }Thenextoperatorskipstherestofthe currentiterationoftheloopandstartsthenextone.Ifthereisa continueclauseontheloop,itisexecutedjust beforetheconditionisre-evaluated,justlikethethirdcomponent ofathree-partforloop.Thusitcanbeusedto incrementaloopvariable,evenwhenaparticulariterationofthe loophasbeeninterruptedbyanext:LINE:while(){ nextLINEif/^#/;#skipcomments nextLINEif/^$/;#skipblanklines … }continue{ $count++; }Theredooperatorrestartstheloopblock withoutevaluatingtheconditionalagain.The continueblock,ifany,isnotexecuted.This operatorisoftenusedbyprogramsthatwanttofibtothemselves aboutwhatwasjustinput.Supposeyouwereprocessingafilethat sometimeshadabackslashattheendofalinetocontinuethe recordonthenextline.Here'showyoucoulduse redoforthat:while(<>){ chomp; if(s/\\$//){ $_.=<>; redounlesseof;#don'treadpasteachfile'seof } #nowprocess$_ }whichisthecustomaryPerlshorthandforthemoreexplicitly (andtediously)writtenversion:LINE:while(defined($line=)){ chomp($line); if($line=~s/\\$//){ $line.=; redoLINEunlesseof(ARGV); } #nowprocess$line }Here'sanexamplefromarealprogramthatusesall threeloop-controloperators.Althoughthisparticularstrategyof parsingcommand-lineargumentsislesscommonnowthatwehavethe Getopts::*modulesbundledwithPerl,it'sstill aniceillustrationoftheuseofloop-controloperatorsonnamed, nestedloops:ARG:while(@ARGV&&$ARGV[0]=~s/^-(?=.)//){ OPT:for(shift@ARGV){ m/^$/&&do{nextARG;}; m/^-$/&&do{lastARG;}; s/^d//&&do{$Debug_Level++;redoOPT;}; s/^l//&&do{$Generate_Listing++;redoOPT;}; s/^i(.*)//&&do{$In_Place=$1||".bak";nextARG;}; say_usage("Unknownoption:$_"); } }Onemorepointaboutloop-controloperators.Youmay havenoticedthatwearenotcallingthem"statements".That's becausetheyaren'tstatements--althoughlikeanyexpression,they canbeusedasstatements.Youcanalmostthinkofthemasunary operatorsthatjusthappentocauseachangeincontrolflow.Soyou canusethemanywhereitmakessensetousetheminanexpression. Infact,youcanevenusethemwhereitdoesn'tmakesense.One sometimesseesthiscodingerror:openFILE,$file orwarn"Can'topen$file:$!\n",nextFILE;#WRONGTheintentisfine,butthenextFILEis beingparsedasoneoftheargumentstowarn, whichisalistoperator.Sothenextexecutes beforethewarngetsachancetoemitthe warning.Inthiscase,it'seasilyfixedbyturningthe warnlistoperatorintothe warnfunctioncallwithsomesuitablysituated parentheses:openFILE,$file orwarn("Can'topen$file:$!\n"),nextFILE;#okayHowever,youmightfinditeasiertoreadthis:unless(openFILE,$file){ warn"Can'topen$file:$!\n"; nextFILE; }[3]Thatis,thefalloutfromthelooptendstooccur automatically. GetProgrammingPerl,3rdEditionnowwiththeO’Reillylearningplatform. O’Reillymembersexperienceliveonlinetraining,plusbooks,videos,anddigitalcontentfromnearly200publishers. Startyourfreetrial Don’tleaveempty-handed GetMarkRichards’sSoftwareArchitecturePatternsebooktobetterunderstandhowtodesigncomponents—andhowtheyshouldinteract. It’syours,free. Getitnow Close



請為這篇文章評分?