closure 參數的省略,神奇的 $0,$1 & $2 (Shorthand Argument Names)

Swift 的 closure 有很多精簡省略的寫法,幫助我們加班打 code 不再手酸。接下來我們將介紹其中最特別,最像火星文的參數省略寫法,Shorthand Argument Names。

當 closure { } 的程式碼欲存取傳入的參數時, 可透過內建的秘密代號存取,$0 代表第一個參數,$1 代表第二個參數,其它以此類推。當我們透過 $0、$1 存取,原本的參數宣告也就沒有存在的價值,因此我們可以一口氣將 closure 的參數,回傳型別 & in 全部移除 !

比方以下程式將 array songs 用 shuffle 隨機排序,然後呼叫 function firstIndex(where:),找出 happySong 在 array songs 裡的位置。

struct Song {
let name: String
let singer: String
}

let happySong = Song(name: "有點甜", singer: "汪蘇瀧")
let sadSong = Song(name: "苦笑", singer: "汪蘇瀧")
var songs = [happySong, sadSong]
songs.shuffle()
let happySongIndex = songs.firstIndex { song in
song.name == happySong.name
}

省略參數的例子: firstIndex & sorted

我們可以在呼叫 firstIndex 時採用參數省略的寫法,改用 $0 存取 songs 裡的歌,將參數,回傳型別 & in 全都省略。

let happySongIndex = songs.firstIndex {
$0.name == happySong.name
}

array 呼叫排序的 sorted function 時也可以省略參數,由於它有兩個參數,所以我們以 $0.grade > $1.grade 指定 array 裡分數高的學生排在前面。

struct Student {
let name: String
let grade: Int
}

var students = [Student(name: "Hook", grade: 52), Student(name: "Peter", grade: 98)]
students = students.sorted {
$0.grade > $1.grade
}

透過 $0、$1 存取參數十分精簡,但這樣子的精簡不見得好,因為它將讓程式的可讀性變差,不易看出參數代表的意義。因此除非在類似剛剛的 firstIndex & sorted 例子,不會對程式可讀性造成影響時,才適合採用如此精簡的做法。

closure 參數省略的注意事項

一旦採用如此極致的精簡,連參數也移除,有一個額外的規定也要遵守。在 closure 的 { } 裡一定要使用 $ 搭配最大數字的秘密代號,因為此數字將決定 closure 接收的參數數量。

以 firstIndex 為例,closure 裡要用到 $0,因為 closure 接收的參數數量是 1 個。

以 sorted 為例,closure 裡要用到 $1,因為 closure 接收的參數數量是 2 個。

一旦決心要殺人,就要斬草除根,否則可是會春風吹又生。同樣的道理,若要省略參數,必須連之後的回傳型別和 in 一併省略。在 closure 的 { } 裡若是沒有參數, 只有回傳型別和 in,將冒出我們最不想看到的紅色錯誤。

手動輸入 closure & $0 比自動完成還方便

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com