国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

非你所想Scala@我不是你想的那樣的匿名函數(shù)

2019-11-11 05:24:40
字體:
供稿:網(wǎng)友

Scala 非常重視代碼的簡(jiǎn)明扼要,形如arg => exPR的匿名函數(shù), 可以很明顯的體現(xiàn)函數(shù)的結(jié)構(gòu)體,也可以用在一些含有多條語句的復(fù)雜函數(shù)上。 對(duì)于自解釋參數(shù)名的函數(shù),我們更優(yōu)雅的選擇是使用占位符,以避免對(duì)參數(shù)進(jìn)行聲明,例如

List(1, 2).map { i => i + 1 }

可以簡(jiǎn)化成 :

List(1, 2).map { _ + 1 }

這兩個(gè)表達(dá)式是等價(jià)的,在REPL里執(zhí)行的結(jié)果也一樣,如果我們加入一段debug語句,來看看表達(dá)式的運(yùn)行過程將會(huì)如何呢? List(1, 2).map { i => println("hi"); i + 1 } List(1, 2).map { println("hi); _+ 1 } 讓我們來猜測(cè)一下,這兩段代碼運(yùn)行的結(jié)果將會(huì)如何。。。

1. 第一種可能,程序?qū)⒋蛴。? Hi List[Int] = List(2, 3) Hi List[Int] = List(2, 3)2. 第二種可能,程序?qū)⒋蛴。? Hi Hi List[Int] = List(2, 3) Hi Hi List[Int] = List(2, 3)3. 第三種可能,程序?qū)⒋蛴。? Hi List[Int] = List(2, 3) Hi Hi List[Int] = List(2, 3)4. 第四種可能: 第一段代碼打印 Hi Hi List[Int] = List(2, 3) 第二段程序?qū)?bào)編譯錯(cuò)誤

你已經(jīng)選好了答案, 現(xiàn)在我們把代碼輸入REPL,看看運(yùn)行結(jié)果是不是和預(yù)想的一致, coding。。。 enter。。。 Author:mark

scala> List(1, 2).map { i => println("Hi"); i + 1 } Hi Hi res23: List[Int] = List(2, 3)scala> List(1, 2).map { println("Hi"); _ + 1 } Hi res25: List[Int] = List(2, 3)

此刻,我心中有一萬頭草泥馬在蹦騰, why, why,why ! 我們只是用占位符簡(jiǎn)化了表達(dá)式的寫法,但是程序運(yùn)行邏輯怎么就不一樣了呢? 因?yàn)槟涿瘮?shù)經(jīng)常作為參數(shù)傳遞,通常情況下都是以{}包圍起來,順其自然,我們會(huì)認(rèn)為在一對(duì)大括號(hào)內(nèi)的代碼就是一整段函數(shù)體, 但實(shí)際上這個(gè)只是為了分隔代碼塊,一行或者多行語句,最終決定了這個(gè)代碼塊的結(jié)果。 這兩個(gè)代碼塊如何被解析將決定程序執(zhí)行的行為,{ i => println(“Hi”); i + 1 } 遵守形式 arg => exprprintln(“Hi”); i + 1 屬于同一段代碼塊,所以println語句是方法體的一部分,方法每調(diào)用一次,println語句就將執(zhí)行一次。

scala> val printAndAddOne =(i: Int) => { println("Hi"); i + 1 }printAndAddOne: Int => Int = <function1>scala> List(1, 2).map(printAndAddOne)HiHires29: List[Int] = List(2, 3)

但是第二段語句,代碼塊表示的兩個(gè)表達(dá)式:println(“Hi”)_+1,并且 _+1map()函數(shù)的輸出結(jié)果,println并不是函數(shù)體的一部分,只有在給map賦值時(shí)會(huì)執(zhí)行。

scala> val printAndReturnAFunc ={ println("Hi"); ( _: Int ) + 1 }HiprintAndReturnAFunc: Int => Int = <function1>scala> List(1, 2).map(printAndReturnAFunc)res30: List[Int] = List(2, 3)

上面的說的一定滿足不了喜歡刨根問底的人,show me the turth,寫到這里,必須得拿出點(diǎn)兒證據(jù)。scala 代碼最終會(huì)編譯成class文件,用反編譯工具,我們可以看到編譯器理解的代碼。

public final void delayedEndpoint$anonymous$AnonymousFunction$1() { Predef..MODULE$.println("hi");List..MODULE$.apply(Predef..MODULE$.wrapIntArray(new int[] { 1, 2 })).map(new AbstractFunction1.mcII.sp() { public static final long serialVersionUID = 0L; public int apply$mcII$sp(int x$1) { return x$1 + 1; } public final int apply(int x$1) { return apply$mcII$sp(x$1); } }, List..MODULE$.canBuildFrom()); }

忽略掉其他無關(guān)信息,我們可以清楚的看到Predef..MODULE$.println(“hi”); 這段語句在方法執(zhí)行體之外,這樣也就驗(yàn)證了為什么只會(huì)打印一次。 scala鼓勵(lì)我們使用精簡(jiǎn)的表達(dá)式,但是在使用占位符簡(jiǎn)化表達(dá)式時(shí),我們需要清楚我們?cè)诟墒裁矗苊獬霈F(xiàn)一些奇奇怪怪的bug。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 新巴尔虎左旗| 安平县| 乌拉特中旗| 十堰市| 黎川县| 门源| 于田县| 洞口县| 五峰| 东至县| 马龙县| 抚宁县| 台前县| 宁城县| 亳州市| 内黄县| 伽师县| 山西省| 琼海市| 十堰市| 大埔区| 洛阳市| 黑水县| 遂平县| 普兰店市| 泊头市| 宝丰县| 新乡县| 新沂市| 吴江市| 湖口县| 义马市| 自治县| 马尔康县| 花莲县| 正安县| 丰镇市| 台山市| 六枝特区| 明星| 武夷山市|