官术网_书友最值得收藏!

7.6 沒有break和continue的日子

你可能已經注意到了,我們并沒有提到breakcontinue。Scala去掉了這兩個命令,因為它們與接下來一章會講到的函數字面量不搭。在while循環中,continue的含義是清楚的,不過在函數字面量中應該是什么含義才合理呢?雖然Scala同時支持指令式和函數式的編程風格,但是在這個具體的問題上,它更傾向于函數式編程風格,以換取語言的簡單。不過別擔心,就算沒有了breakcontinue,還有很多其他方式可以用來編程。而且,如果你用好了函數字面量,則使用這里提到的其他方式通常比原來的代碼更短。

最簡單的方式是用if換掉每個continue,用布爾值換掉每個break。布爾值表示包含它的while循環是否繼續。例如,假設你要檢索參數列表,找一個以“.scala”結尾但不以連字符開頭的字符串,那么用Java的話,你可能會這樣寫(如果你喜歡while循環、breakcontinue):

如果要將這段Java代碼按字面含義翻譯成Scala代碼,則可以將“先ifcontinue”這樣的寫法改成用if將整個while循環體包起來。為了去掉break,通常會添加一個布爾值的變量,表示是否繼續循環,不過在本例中可以直接復用foundIt。通過使用上述兩種技巧,代碼看上去如示例7.16所示。

示例7.16 不使用breakcontinue的循環

示例7.16的Scala代碼與原本的Java代碼很相似:所有基礎的組件都在,順序也相同。另外,還有兩個可被重新賦值的變量和一個while循環,而在循環中有一個對i是否小于args.length的檢查、一個對"-"的檢查和一個對".scala"的檢查。

如果你想去掉示例7.16中的var,一種做法是將循環重寫為遞歸的函數。比如,可以定義一個searchFrom函數,接收一個整數作為輸入,從那里開始向前檢索,然后返回找到的入參下標。通過使用這個技巧,代碼看上去如示例7.17所示。

示例7.17 用于替代var循環的遞歸

示例7.17的這個版本采用了對用戶來說有意義的函數名,并且使用遞歸替換了循環。每一個continue都被替換成一次以i + 1作為入參的遞歸調用,從效果上講,跳到了下一個整數值。一旦習慣了遞歸,很多人都會認為這種風格的編程方式更易于理解。

注意

Scala編譯器實際上并不會對示例7.17中的代碼生成遞歸的函數。由于所有的遞歸調用都發生在函數尾部tail-call position),因此編譯器會生成與while循環類似的代碼。每一次遞歸都會被實現成跳回函數開始的位置。8.10節將會對尾遞歸優化做更詳細的討論。

主站蜘蛛池模板: 东乌珠穆沁旗| 金门县| 木里| 兴隆县| 新野县| 皋兰县| 星座| 花莲县| 长岭县| 呼玛县| 滨海县| 镇江市| 乐亭县| 浮山县| 兴隆县| 衡水市| 辽宁省| 平乐县| 湘潭县| 平阴县| 旌德县| 资溪县| 德兴市| 九台市| 景泰县| 城步| 紫金县| 兴隆县| 天台县| 武威市| 固阳县| 莎车县| 酒泉市| 南京市| 石泉县| 枣庄市| 龙陵县| 绥芬河市| 丹棱县| 康保县| 惠来县|