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

首頁 > 學院 > 開發設計 > 正文

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

2019-11-11 05:59:01
字體:
來源:轉載
供稿:網友

Scala 非常重視代碼的簡明扼要,形如arg => exPR的匿名函數, 可以很明顯的體現函數的結構體,也可以用在一些含有多條語句的復雜函數上。 對于自解釋參數名的函數,我們更優雅的選擇是使用占位符,以避免對參數進行聲明,例如

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

可以簡化成 :

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

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

1. 第一種可能,程序將打印: Hi List[Int] = List(2, 3) Hi List[Int] = List(2, 3)2. 第二種可能,程序將打印: Hi Hi List[Int] = List(2, 3) Hi Hi List[Int] = List(2, 3)3. 第三種可能,程序將打印: Hi List[Int] = List(2, 3) Hi Hi List[Int] = List(2, 3)4. 第四種可能: 第一段代碼打印 Hi Hi List[Int] = List(2, 3) 第二段程序將報編譯錯誤

你已經選好了答案, 現在我們把代碼輸入REPL,看看運行結果是不是和預想的一致, 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 ! 我們只是用占位符簡化了表達式的寫法,但是程序運行邏輯怎么就不一樣了呢? 因為匿名函數經常作為參數傳遞,通常情況下都是以{}包圍起來,順其自然,我們會認為在一對大括號內的代碼就是一整段函數體, 但實際上這個只是為了分隔代碼塊,一行或者多行語句,最終決定了這個代碼塊的結果。 這兩個代碼塊如何被解析將決定程序執行的行為,{ i => println(“Hi”); i + 1 } 遵守形式 arg => exprprintln(“Hi”); i + 1 屬于同一段代碼塊,所以println語句是方法體的一部分,方法每調用一次,println語句就將執行一次。

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)

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

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,寫到這里,必須得拿出點兒證據。scala 代碼最終會編譯成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()); }

忽略掉其他無關信息,我們可以清楚的看到Predef..MODULE$.println(“hi”); 這段語句在方法執行體之外,這樣也就驗證了為什么只會打印一次。 scala鼓勵我們使用精簡的表達式,但是在使用占位符簡化表達式時,我們需要清楚我們在干什么,避免出現一些奇奇怪怪的bug。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 阳信县| 信宜市| 和政县| 五家渠市| 白水县| 普定县| 镇安县| 乐清市| 纳雍县| 沐川县| 景宁| 行唐县| 托克逊县| 洛浦县| 太白县| 谢通门县| 治多县| 樟树市| 大城县| 芷江| 北宁市| 普格县| 阳城县| 双峰县| 高清| 阿城市| 防城港市| 津南区| 岳普湖县| 简阳市| 绥江县| 资兴市| 浦北县| 蓬溪县| 镇巴县| 环江| 敖汉旗| 晋江市| 德保县| 崇左市| 崇左市|