鉴于这种简单的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 ...
似乎不起作用。
答案 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
好的发现!
答案 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)