iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
自我挑戰組

連續30天 初學者介紹Scala語言系列 第 13

[Day 13]Scala 函式與閉包 Part3

  • 分享至 

  • xImage
  •  
  • Partially applied functions 部分套用函式
  • Closures 閉包

昨天介紹了函式常量跟函式值的應用,還有如何精簡地表示它們
今天要來介紹部分套用函式(Partially applied functions)
先來看以下的程式:

def product(x: Int, y: Int, z: Int) = x * y * z
product(1, 2, 3)    //Output = 6

這是一個簡單的求三個數相乘的函式
另外在Scala裡,當我們呼叫一個有參數的函式時,我們其實是在對那個參數套用函式。
因此,當所有參數都傳給函式時,我們對所有參數完全套用了函式。
但是當我們只給函式傳進少於它所需要的參數個數時,這樣的表達式就是部分套用函式(Partially applied functions)
如下:

def product(x: Int, y: Int, z: Int) = x * y * z
val a = product _
a(2, 3, 4)    //Output = 24

Scala編譯器會把a(2, 3, 4)看成是對函式值的apply方法調用
也就是說a(2, 3, 4)

a.apply(2, 3, 4)

的簡寫
再來看另一個例子

val b = product(2, _, 4)
b(10)    //Output = 80
//b.apply 呼叫 sum(2, 10, 4)

這邊我們提供了第一個跟最後一個引數給product,缺少第二個。
所以Scala編譯器這時會生成一個新函式包含只接收一個引數的apply方法
當只用那一個引數呼叫時,這個新生成的函式的apply方法會去呼叫product,並依序傳進第一個引數、傳給新函式的引數以及第三個引數。

Real-world example

當我們在操作HTML時可能會有個方法用來把前綴(prefix)、後綴(suffix)加進HTML片段,例如:

def wrap(prefix: String, html: String, suffix: String) = 
    prefix + html + suffix

如果對於不同的HTML我們都想要加進相同的前綴和後綴,那我們可以對方法套用那兩個前綴後綴參數,不套用HTML參數,如:

val wrapWithDiv("<div>", _, "<div>")

接著我們來談閉包(Closure)

在談閉包之前,我們要先來說說自由變數(free variable)和綁定變數(bound variable)。
先來看以下函式:

(x: Int) => x + increase

在這個情況下,increase是一個自由變數,因為函式常量並沒有賦予它任何意義
相比之下,x就是一個綁定變數,因為在函式裡它有明確的定義:Int參數

val increase = 1
val more = (x: Int) => x + increase
more(10)    //Output = 11

簡單來說,閉包指的是捕獲了自由變數的函式物件,之所以叫做“閉包”是因為它在創建時包住了當時可見的變數。

今天就介紹到這邊
/images/emoticon/emoticon33.gif


上一篇
[Day 12]Scala 函式與閉包 Part 2
下一篇
[Day 14]Scala Currying
系列文
連續30天 初學者介紹Scala語言30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言