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

  • Scala編程(第5版)
  • (德)馬丁·奧德斯基等
  • 1288字
  • 2022-05-06 15:51:34

第12步 用map方法和for-yield變換

在指令式編程風(fēng)格中,可以當場改變數(shù)據(jù)結(jié)構(gòu)直到達成算法的目標。而在函數(shù)式編程風(fēng)格中,需要把不可變的數(shù)據(jù)結(jié)構(gòu)變換成新的數(shù)據(jù)結(jié)構(gòu)來達成目標。

不可變集合的一個重要的用于實現(xiàn)函數(shù)式變換的方法是map。與foreach方法相同,map方法也接收一個函數(shù)作為參數(shù)。與foreach方法不同的是,foreach方法用傳入的函數(shù)對每個元素執(zhí)行副作用,而map方法用傳入的函數(shù)將每個元素變換成新的值。舉例來說,如下字符串的列表:

可以像這樣將它變換成由新的字符串組成的新列表:

另一種執(zhí)行這個變換的方式是使用for表達式。可以通過yield關(guān)鍵字(而不是do)來引入需要執(zhí)行的代碼體:

for-yield生成的結(jié)果與map方法生成的結(jié)果完全一樣,因為編譯器會把for-yield表達式變換成map方法調(diào)用。[11]由于map方法返回的列表包含了由傳入的函數(shù)生成的值,因此返回的列表的元素類型將會是該函數(shù)的結(jié)果類型。在前一例中,傳入的函數(shù)返回的是字符串,因此map方法返回List[String]。如果傳入map方法的函數(shù)返回其他類型,則map方法返回的List也會以相應(yīng)的類型作為其元素類型。例如,在下面的map方法調(diào)用中,傳入的函數(shù)將字符串變換成整數(shù)來表示字符串元素的長度。因此,map方法調(diào)用的結(jié)果就是包含了這些長度的List[Int]

像以前一樣,你也可以用帶有yieldfor表達式來完成同樣的變換:

很多類型都可以使用map方法,不僅僅是List。這讓我們可以在很多類型上使用for表達式。比如說Vector,這是一個對所有它支持的操作提供“實效常量時間”(effectively constant time)性能的不可變序列。由于Vector具備帶有正確簽名的map方法,因此可以對Vector執(zhí)行像List一樣的函數(shù)式變換,可以直接調(diào)用map方法,也可以使用for-yield。例如:

請注意,當你對List執(zhí)行map操作時,得到的返回值是一個新的List;而當你對Vector執(zhí)行map操作時,得到的返回值是一個新的Vector。你會發(fā)現(xiàn)絕大多數(shù)定義了map方法的類型都具備這個模式。

最后再看一個例子,Scala的Option類型。Scala用Option表示可選的值,而不使用像Java一樣用null表達此含義的傳統(tǒng)技法。[12]Option要么是一個Some,表示值存在;要么是一個None,表示沒有值。

作為一個展示Option實際使用的案例,我們可以考查一下find方法。所有的Scala集合類型,包括ListVector,都具備find方法,其作用是查找滿足給定前提的元素,這個前提是一個接收元素類型的參數(shù)并返回布爾值的函數(shù)。find方法的結(jié)果類型是Option[E],其中,E是集合的元素類型。find方法會逐個遍歷集合的元素,將元素傳遞給前提。如果前提返回了truefind就停止遍歷,并將當前元素包裝在Some中返回。如果find遍歷了所有元素都沒有找到能通過前提判斷的元素,就會返回None。下面是一些結(jié)果類型均為Option[String]的示例:

盡管Option不是一個集合,它也提供了map方法。[13]如果Option是一個Some,可被稱為“已定義”的可選值,則map方法將返回一個新的包含了將原始Some元素傳入map方法后得到返回值的新Option。下面的示例對startsW進行了變換,而它本來是一個包含字符串"Who"Some

ListVetcor相同,可以通過對Option執(zhí)行for-yield來完成這個變換:

如果對None執(zhí)行mapNone意味著這是一個“未定義”的可選值,將得到一個None。下面是一個展示對startsH(一個None值)執(zhí)行map操作的示例:

for-yield完成同樣的變換操作:

還可以用map方法和for-yield對其他許多類型進行變換,但就目前而言足夠了。這一步的主要目的是讓你對如何編寫典型的Scala代碼有一個直觀的認識:對不可變數(shù)據(jù)結(jié)構(gòu)進行函數(shù)式變換。

主站蜘蛛池模板: 新兴县| 德阳市| 旺苍县| 冷水江市| 博湖县| 吉水县| 文安县| 永善县| 诸暨市| 临城县| 平度市| 濉溪县| 嘉义县| 海门市| 皋兰县| 通榆县| 抚远县| 平谷区| 苗栗市| 吴堡县| 太保市| 安溪县| 荃湾区| 临沭县| 绥中县| 万州区| 饶阳县| 永胜县| 策勒县| 拉孜县| 乌拉特前旗| 固镇县| 平舆县| 奎屯市| 铜鼓县| 信宜市| 灌阳县| 青岛市| 新密市| 恩平市| 德昌县|