2015-09-05 58 views
3

enter image description here在Swift中聲明函數類型的變量有什麼意義?

我得到這個從一本書,這個代碼在didSet方法使用,我爲什麼時,你可以編寫調用兩個函數放緩()或函數加速功能,這將是有益的困惑()??這基本上是聲明一個「可變函數」和「設置它等於它自己的定義」,然後返回一個「函數」? (如我錯了請糾正我)。爲什麼需要使用一個變量,並將其設置爲等於定義時,我可以創建一個函數?那有什麼用處?

+2

簡而言之,將函數視爲一級成員允許函數被存儲,作爲參數傳遞(高階函數)等等。雖然它們的使用可能不明顯從您提供的示例中,查看https://en.wikipedia.org/wiki/First-class_function#Higher-order_functions:_passing_functions_as_arguments – Roshan

回答

5

當你開始學習函數文字,取得和返回其他函數的函數,以及包含函數的變量時,所有新的模式都會打開。這是編程中最強大的工具之一。

您的描述不完全正確。這不是「設定它等於自己的定義」。它將函數看作是值,就像整數,布爾值或結構一樣。當你把一個函數看作一個值時,你可以組合函數,就像你結合其他值一樣。這是非常強大的。

讓我們考慮基於你只是一個很簡單的例子:

var speed = 0 
func speedup() { speed++ } 
func slowdown() { speed-- } 
var changeSpeed = speedup 

speed // 0 
changeSpeed() 
speed // 1 

OK很大。但正如你所說,我們可以設定一個布爾或什麼,只是做了我們想做的事情。但是,讓我們把它進一步:

func twice(f:() -> Void) -> (() -> Void) { return { f(); f() } } 

這是一個函數,函數返回一個新的函數,它兩倍的第一個。再讀一遍,並考慮一下。這是一個函數,它可以使用函數,並且可以使增加。我們不在乎這個功能是什麼。我們可以加倍任何東西

因此,讓我們加倍我們改變功能:

changeSpeed = twice(changeSpeed) 
changeSpeed() 
speed // 3 

我們沒有修改speedup處理這個問題。 twice不關心我們是否通過speedupslowdown或我們未來可能發明的其他功能。我們有很多種方法可以擴展這些代碼,而無需重寫任何原始代碼。我們可以訪問twice等更高階的函數。這些功能可以實現或返回其他功能,而且它們非常強大。在雨燕,它們包括像mapfilter,這一切都依賴於創造文字的功能,並將它們分配到事物的能力。

讓我們再走一步。不要擔心這個代碼中的所有想法,只是它允許我們做什麼。

import Darwin 

var speed = 0 
func speedup() { speed++ } 
func slowdown() { speed-- } 

var changeSpeed:() throws ->() = speedup 

// This funny syntax lets us more easily create a function that takes a 
// function and retries it some number of times. It's called "currying". 
// But the point is that calling `retry` will create a new function that 
// retries the given function. 
func retry(n: Int)(_ f:() throws -> Void)() rethrows { 
    for _ in 1..<n { 
     do { 
      try f() 
      return 
     } catch { 
      print("It failed. Let's try it again!") 
     } 
    } 
    // One last try. If it fails, so we do we 
    try f() 
} 

struct FailedError : ErrorType {} 

// Similarly, `maybe` takes a function and might choose not to run it 
func maybe(p: Float)(_ f:() throws ->())() throws { 
    if Float(arc4random())/Float(INT32_MAX) < p { 
     try f() 
    } else { 
     throw FailedError() 
    } 
} 

// With that, we can create a function called "lotsOfTries" that tries 
// other functions 10 times. Yes, we're creating a function with `let`. 
let lotsOfTries = retry(10) 

// And we can create a function that fails other functions most of the time. 
let badChance = maybe(0.15) 

// And then we can glue them all together without knowing how they work internally. 
changeSpeed = lotsOfTries(badChance(speedup)) 

do { 
    try changeSpeed() 
    print(speed) 
} catch { 
    print("Couldn't do it, sorry") 
} 

所以這些是你可以建立的功能,一旦你真的擁抱這種編碼。在我自己的代碼,我使用類似retry功能,因爲「重試若干次,但僅適用於特定類型的錯誤,並沒有太多的時間」是獨立的什麼東西被試一個非常複雜的問題。我創建了將調用記錄到其他函數的函數,這對於一致的日誌記錄來說非常方便。我有一個執行身份驗證,然後換行不進行代理那套其他 HTTP請求處理程序....這是怎樣構圖功能的工作原理其他 HTTP請求處理程序,它可以真正改變你怎麼寫的HTTP請求處理程序程式。

而且,在最簡單的情況下,這可以讓我們做回調。所以,時不時地出現......

+0

哇!我剛剛登錄並閱讀了您的答案,您是我的朋友,擁有出色的才能!我對這個問題有點清楚,但對我來說它仍然有點新,但是你剛寫的內容令人難以置信,我很佩服!我們可以聯繫,也可以一起在一個項目上工作嗎? – Ali

相關問題