2017-08-13 62 views
0

正如Documentation提到 - Autoclosure科:Swift autoclosure如何延遲工作?

的autoclosure 可延遲評價,因爲裏面 代碼不運行,直到您調用關閉。對於有副作用或計算成本很高的代碼,延遲評估是有用的 ,因爲它允許您控制代碼的評估時間。

我無法準確理解延遲背後的邏輯是什麼。

當我試圖標準閉合和autoclosure之間進行比較:

func getMyString() -> String { 
    print("Reaching My String") 
    return "My String" 
} 

func testStandardClousre(closure:() -> String, isValid: Bool) { 
    print("Reaching Test") 

    if isValid { 
     _ = closure() 
    } 
} 

// calling: 
testStandardClousre(closure: {() -> String in 
    return getMyString() 
}, isValid: false) 

當然,因爲closure不會被執行,輸出將是:

到達測試

沒有打印「到達我的字符串」,即沒有到達getMyString()

如果這時候關閉標記爲@autoclosure確切的情況下(給出相同的輸出):

func testAutoClosure(closure: @autoclosure() -> String, isValid: Bool) { 
    print("Reaching Test") 

    if isValid { 
     _ = closure() 
    } 
} 

// calling 
testAutoClosure(closure: getMyString(), isValid: false) 

那麼什麼是拖延的意思?即如何延遲工作?

+1

下面是今天的一個例子,爲什麼拖延是有用的:https://stackoverflow.com/a/45659765/1630618 – vacawama

+0

這是一篇很棒的博客文章,展示了autoclosure是如何產生的:https://developer.apple.com/swift/blog/?id=4 – Alexander

回答

1

您的代碼片段不能成爲延遲的一個很好的示例。如果你想找到什麼推遲的意思,你需要比較@autoclosure非關閉。

非閉合的一個例子:

enum LogLevel: Int { 
    case debug, warning, error 
} 

extension LogLevel: Comparable { 
    static func < (lhs: LogLevel, rhs: LogLevel) -> Bool { 
     return lhs.rawValue < rhs.rawValue 
    } 
} 

var currentLogLevel: LogLevel = .error 
func outputLogNonClosure(_ level: LogLevel, message: String) { 
    if level >= currentLogLevel { 
     print(message) 
    } 
} 

outputLogNonClosure(.debug, message: "Debug message") 
//output nothing, calling cost can be acceptable. 

有時,可能需要通過複雜的運算的結果,以產生錯誤消息。

func getMyStringSuperHeavy() -> String { 
    var result = "" 
    do { 
     print("Assume doing very complex calculation to get Debug message...") 
     result = "Debug message" 
    } 
    return result 
} 

outputLogNonClosure(.debug, message: getMyStringSuperHeavy()) 
//->Assume doing very complex calculation to get Debug message...... 
//The result of `getMyStringSuperHeavy()` is not used, but `getMyStringSuperHeavy()` is called. 

在上述後者的代碼,則可能需要getMyStringSuperHeavy()不不需要輸出時進行評估。


autoclosure的一個例子:

func outputLogAutoClosure(_ level: LogLevel, message: @autoclosure()->String) { 
    if level >= currentLogLevel { 
     print(message()) 
    } 
} 

outputLogAutoClosure(.debug, message: "Debug message") 
//output nothing, calling cost can be acceptable. 

outputLogAutoClosure(.debug, message: getMyStringSuperHeavy()) 
//output nothing, calling cost can be acceptable as well. 

在最後的碼,的getMyStringSuperHeavy()評價是延遲 ED直到該值實際使用。


總體參數的計算成本聲明爲arg: AType不能省略,但可能不被需要的價值在某些情況下,你可以把它改成arg: @autoclosure()->AType,並使用arg()真正需要它的值時。

@autoclosure可以在其他一些情況下可以使用,但你在任何情況下比較arg: ATypearg: @autoclosure()->AType

+0

謝謝你的回答。老實說,我有點驚訝,在第二個代碼片段'getMyStringSuperHeavy()'已被評估!你能解釋爲什麼嗎?我的意思是我認爲它不應該被評估......我認爲這是我想念的部分。 –

+0

另一個問題是:如果我們使用非autoclosure參數嘗試相同的函數:func outputLogClosure(_ level:LogLevel,message:() - > String)如果level> = currentLogLevel {print(message()) } }'我們假設我們這樣稱呼它:'outputLogClosure(.debug){() - > 中的字符串返回「my message」 }它會導致autoclosure參數的行爲是否相同?我真的很感激你的時間和考慮:) –

+0

@AhmadF,第一點。假設你的意思是'outputLogNonClosure(.debug,message:getMyStringSuperHeavy())'。在這個例子中,'outputLogNonClosure'是通常的函數,當Swift調用通常的函數時,Swift會計算所有實際參數,並將結果放入寄存器或堆棧中,然後調用實際函數處理。這種行爲在很多主要語言,C#或Java或Objective-C中都很常見。第二,@AhmadF, – OOPer