为什么curried函数需要外部参数名称?

时间:2014-06-11 19:19:11

标签: swift currying

鉴于这种简单的currying功能:

func foo(x:Int)(y:Int)->String{
  return "\(x) with \(y)"
}

我希望能够做到这样的事情:

let bar = foo(1)
bar(2) //<- error: Missing argument label 'y:' in call

如果我将呼叫标记为bar(如在bar(y:2)中),则一切正常。但我不明白为什么参数名称是必要的。有什么方法可以避免吗?

显而易见的事情:

func foo(x:Int)(_ y:Int)->String ...

似乎不起作用。

5 个答案:

答案 0 :(得分:8)

这是一个错误,你应该在bugreport.apple.com

提交雷达

作为确认,如果你放置一个下划线,就像这样

func foo(x: Int)(_ y: Int) -> String

你收到警告

  

外来&#39; _&#39;在参数:&#39; y&#39;没有关键字参数名称

所以它明确地说y没有外部名称,但在调用时仍需要一个,这显然违背了语言规范。

答案 1 :(得分:1)

我认为这是一个编译器错误,你的例子应该像Swift Programming Language一书中描述的那样工作,他们提到了声明curried函数:

func addTwoNumbers(a: Int)(b: Int) -> Int {
    return a + b
}

addTwoNumbers(4)(5) // Returns 9

https://bugreport.apple.com

好的发现!

答案 2 :(得分:0)

我不确定我是否完全理解你的干扰。这是我的看法。我有一个函数foo如下:

func foo(x:Int, y:Int) -> String{
  return "\(x) with \(y)"
}

let bar = foo(1, 2) // gives "1 with 2"

我希望将此功能用于修复&#39; x的值,请按以下步骤操作:

func fooCurry(x:Int) -> (Int -> String) {
  func curry(y:Int) -> String {
    return foo(x, y)
  }
  return curry
}

上面返回一个新函数,可以按如下方式使用:

let curriedFoo = fooCurry(1)
let barWithCurry = curriedFoo(2) // gives "1 with 2"

fooCurry返回的函数具有签名(Int -> String),这意味着该参数没有外部名称。

答案 3 :(得分:0)

不是最好的语法,但是如果你现在想要解决它,你可以使用以下基本的curried函数:

func foo(x:Int) -> Int -> String {
  return {
    return "\(x) with \($0)"
  }
}

然后你可以这样做:

let bar = foo(1)
bar(2) //-> 1 with 2

现在很明显,当你想编写一个用于管道四个Int的curried函数时,问题就变得很明显了:

func makerAdders(a:Int)(b:Int)(c:Int)(d:Int) {...}

变成这样:

func add(a:Int) -> Int -> Int -> Int -> Int {
  return { 
    b in return {
      c in return {
        d in return a + b + c + d 
      }
    }
  }
}

内部闭包使它比使用内部函数更好一些,但它再次违背了良好func add(a:Int)(b:Int)(c:Int)(d:Int) {return a+b+c+d}语法的目的。

答案 4 :(得分:0)

据我所知,绝对是编译器中的错误。在它修复之前,你可以使用这些函数获得任何函数的正确curry版本(注意我已经包含了两个和三个参数的案例,在你的闲暇时间延伸:

func curry<A,B,C>(f: (A, B) -> C) -> A -> B -> C {
    return { a in { b in return f(a,b) } }
}

func curry<A,B,C,D>(f: (A, B, C) -> D) -> A -> B -> C -> D {
    return { a in { b in { c in return f(a,b,c) } } }
}

只需使用:

curry(addTwoNumbers)(1)(2)