我在Swift
中看到一个函数可以返回另一个函数。我不习惯这个概念,我很难理解你什么时候想做这个?
当有人想要从另一个函数返回函数时,有人能指出一个很好的例子吗?
答案 0 :(得分:4)
首先,我想说我在Swift中读得不是很好,但这适用于任何返回函数的函数:
另外,我必须指出,如果您了解currying,这会更容易理解。
看看partial function application。在部分应用程序中,你接受一个函数(让我们以一个简单的add
函数为例),并为它提供比实际需要的参数更少的参数,以产生它的假设结果。结果如果这是一个接受其余参数的函数。咖喱add
看起来像这样:
func add(a: Int)(b: Int) -> Int {
return a + b
}
您现在可以执行此操作:
var add10 = add(10)
println(add10(b: 4)) // prints 14
为了能够部分应用功能而不必明确地对每一个功能进行咖喱,请查看this要点。
答案 1 :(得分:1)
这是一个实际的例子,我在自己的应用程序中使用的实用程序函数。
正如您可能知道的那样,在代码中绘制图像是通过这种形式的图案舞蹈来实现的:
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), false, 0)
// do stuff
let im = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// use im here...
这种结构有几个缺点:它是无聊的样板,当然,但更糟糕的是,它的关键目的是生成图像,这发生在倒数第二行 - 但随后图像无法使用直到在最后一行之后(换句话说,结构“掩埋了lede”,隐藏了它自己的目的)。
此外,它容易出错(错误地忽略了UIGraphicsEndImageContext
?)。此外,任何局部变量都会干扰周围范围内的局部变量。
所有这些问题都可以通过带有闭包的实用函数在Swift中轻松解决:
func imageOfSize(size:CGSize, closure:() -> ()) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
closure()
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result
}
你这样称呼它:
self.image = imageOfSize(CGSizeMake(100,100)) {
let con = UIGraphicsGetCurrentContext()
CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100))
CGContextSetFillColorWithColor(con, UIColor.blueColor().CGColor)
CGContextFillPath(con)
}
调用语法更能表达我们正在做的事情(我们正在制作图像并使用它!),它省略了样板并为任何局部变量提供了包含的范围(尽管没有这个例子)。
这非常好,但请注意我在调用UIGraphicsBeginImageContextWithOptions
时必须提供两个默认值,即false
和0
。当然,这些是最常见的默认值。但是编写一个允许我们指定它们的版本,或者至少是第二个参数(不透明或不透明)会很好。
与此同时,不必一直指定,因为false
实际上是最常见的值。因此我们想要的是可选第二个参数opaque:Bool = false
。
问题是,当第三个参数是闭包时,不能有可选的第二个参数;当你在省略第二个参数的同时尝试拨打电话时,编译器会抱怨。
解决方案是将函数“curry”为两个函数,其中:
一个函数需要一个可选的opaque
参数。
另一个函数需要关闭。
像这样:
func drawnImage (opaque:Bool = false) -> (CGSize, () -> ()) -> UIImage {
func imageOfSize(size:CGSize, closure:() -> ()) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, opaque, 0)
closure()
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result
}
return imageOfSize
}
现在你可以这样称呼它:
self.image = drawnImage()(CGSizeMake(100,100)) {
let con = UIGraphicsGetCurrentContext()
CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100))
CGContextSetFillColorWithColor(con, UIColor.blueColor().CGColor)
CGContextFillPath(con)
}
或者,如果不透明,就像这样:
self.image = drawnImage(opaque:true)(CGSizeMake(100,100)) {
let con = UIGraphicsGetCurrentContext()
CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100))
CGContextSetFillColorWithColor(con, UIColor.blueColor().CGColor)
CGContextFillPath(con)
}
因此,函数在Swift中生成函数的能力让我们可以根据自己的意愿弯曲语言,在两种情况下都为我们提供了方便的调用语法。
答案 2 :(得分:0)
func returnfunction() -> ((Int,Int) -> Double)
{
var y = 0
func functionToReturn(number1:Int, number2:Int) -> Double {
y = number1 * number2
return Double(y)
}
return functionToReturn //return function
}
var result = returnfunction()
result (2,4)