返回另一个函数的函数的一个很好的例子是什么?

时间:2014-08-03 17:39:41

标签: swift

我在Swift中看到一个函数可以返回另一个函数。我不习惯这个概念,我很难理解你什么时候想做这个?

当有人想要从另一个函数返回函数时,有人能指出一个很好的例子吗?

3 个答案:

答案 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时必须提供两个默认值,即false0。当然,这些是最常见的默认值。但是编写一个允许我们指定它们的版本,或者至少是第二个参数(不透明或不透明)会很好。

与此同时,不必一直指定,因为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)