咖喱所有swift函数参数,但不要调用该函数

Hea*_*ers 0 currying swift

我有以下快速功能:

func foo(bar: String)(_ baz: String) {
  NSLog("bar \(bar), baz: \(baz)")
}

let f = foo("fizz")("buzz") // won't compile, foo returns Void
Run Code Online (Sandbox Code Playgroud)

我想把它传递给dispatch_async,但我不能,因为我不能在不调用函数的情况下讨论这两个参数.我如何咖喱barbaz没有打电话foo

Lil*_*ard 5

如果您可以自由更改函数声明,Heath的答案是正确的.如果你不想这样做,那么你只需要使用内联闭包,例如

// pre-existing foo definition
func foo(bar: String)(_ baz: String) {
    NSLog("bar \(bar), baz: \(baz)")
}

let f = { foo("fizz")("buzz") }
f()
Run Code Online (Sandbox Code Playgroud)

如果您的问题是要立即评估参数,可以使用捕获列表:

let f = { [a=bar(),b=baz()] in foo(a)(b) }
Run Code Online (Sandbox Code Playgroud)

或者当写为dispatch_async:

dispatch_async(queue) { [a=bar(),b=baz()] in
    foo(a)(b)
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为创建闭包时调用者会立即计算捕获列表(而不是在调用闭包时进行求值).

另一种选择是定义嵌套的curried函数.嵌套函数实际上只是闭包的糖,但它们可以更方便:

/// Function that your code is executing in
func myFunc() {
    // ...

    // define a nested function
    func f(bar: String, baz: String)() {
        foo(bar)(baz)
    }

    // now call it
    dispatch_async(dispatch_get_main_queue(), f("foo", "bar"))
}
Run Code Online (Sandbox Code Playgroud)

附录:我强烈建议不要说NSLog("bar \(bar), baz: \(baz)").NSLog采用格式字符串和参数,因此如果其中任何一个barbaz包含任何看起来像格式标记(例如%@%d)的东西,那么调用NSLog()将表现得很糟糕并可能崩溃.你有两个合理的选择:

  1. NSLog("%@", "bar \(bar), baz: \(baz)")
  2. NSLog("bar %@, baz: %@", bar, baz)

最佳选择取决于您的参数是否已经兼容CVarArg(String但是例如String?不是).另请注意,如果您的参数保证不包含格式标记,例如它们是数字或布尔值,那么您可以继续使用现有的NSLog("bar \(someIntVar) baz \(someBoolVar)")样式.