swift 柯里化

如何将一个接受多参数的函数变换为一系列只接受单个参数的函数,这个过程被称为柯里化 (Currying) 

参照:objc.io|objc 中国


/**

1.add0 add的例子向我们展示了如何将一个接受多参数的函数变换为一系列只接受单个参数的函数,这个过程被称为柯里化 (Currying),它得名于逻辑学家 Haskell Curry;我们将 add 称为 add0 的柯里化版本

2.首先向函数传递第一个参 1,然后将返回的函数应用到第二个参数 2

3.我们甚至可以省略 addTheSome函数的一个 return 关键字和返回类型中的某些括号

addTheSome后写为下面这样:函数中的箭头 ->向右结合。这也就是说,你可以将 A -> B -> C理解为 A -> (B -> C)

*/


func add0(x: Int,_ y: Int) ->Int {

    return x + y }


func add(x:Int)-> (Int ->Int){

    return{y inreturn x + y}

}



func addTheSome(x:Int)->Int -> Int{

    return { y in x + y }

}


add(1)(3)

addTheSome(1)(3)


柯里化 应用封装Core Image 

//封装Core Image

// Filter 类型定义为一个函数,该函数接受一个图像作为参数并返回一个新的图像


typealias Filter = CIImage -> CIImage


/**

 blur 函数返回一个新函数,新函数接受一个 CIImage类型的参数 image, 并返回一个新图像(return  lter .outputImage)

 因此,blur 函数的返回值满足我们之前定义 CIImage -> CIImage,也就是 Filter类型

 */

func blur(radius: Double) -> Filter {

    

    return {image in

        let parameters = [ kCIInputRadiusKey: radius, kCIInputImageKey: image]

        

        guard let  lter =CIFilter(name: "CIGaussianBlur", withInputParameters:parameters)else {fatalError()}

        

        guard let outputImage =  lter.outputImageelse {fatalError()}

        

        return outputImage

    }

}


/**

定义一个生成固定颜色的滤镜

颜色生成 滤镜不检查输入图像。因此,我们不需要给返回函数中的图像参数命名。取而代之,我们使用 

一个匿名参数 _ 来强调滤镜的输入图像参数是被忽略的


*/

func colorGenerator(color: NSColor) -> Filter {

    return { _ in

        guard let c = CIColor(color: color)else { fatalError () }

        let parameters = [kCIInputColorKey: c]

        

        guard let  lter = CIFilter (name:"CIConstantColorGenerator",

            withInputParameters: parameters) else { fatalError() }

        

        guard let outputImage =  lter.outputImageelse { fatalError() }

        

        return outputImage

    }

}


/**

 定义合成滤镜

 

 将输出图像剪裁为与输入图像一致的尺寸严格来说,这不是必须的,而完全取决

 于我们希望滤镜如何工作

 */

func compositeSourceOver(overlay: CIImage) -> Filter {

    return { image in

        let parameters = [ kCIInputBackgroundImageKey: image, kCIInputImageKey: overlay

        ]

        guard let  lter =CIFilter (name: "CISourceOverCompositing",

            withInputParameters: parameters) else {fatalError() }

        

        guard let outputImage =  lter.outputImageelse { fatalError() }

        

        let cropRect = image.extent

        return outputImage.imageByCroppingToRect(cropRect)

    }

}


/**

 

 结合两个滤镜来创建颜色叠层滤镜

 

 返回了一个接受图像作为参数的函数。colorOverlay函数首先调用了 colorGenerator滤镜。

 colorGenerator 滤镜需要一个 color作为参数,然后返回一个新的滤镜,因此代码片段

 colorGenerator(color) Filter 类型。而 Filter类型本身就是一个从 CIImage CIImage 函数;

 因此我们可以向 colorGenerator(color)函数传递一个附加的 CIImage类型的参数,最终我们能够得到一个 CIImage类型的新叠层。这就是我们在定义 overlay的过程中所发生的全部 事情事,可以大致概括为 ——首先使用 colorGenerator函数创建一个滤镜,接着向这个滤镜传递一个 image 参数来创建新图像。与之类似,返回值 compositeSourceOver(overlay)(image)由一个通过 compositeSourceOver(overlay)函数构建 的滤镜和随即被作为参数的 image 组成

 */


func colorOverlay(color:NSColor)->Filter{

    return { image in

        let overlay = colorGenerator(color)(image)

        return compositeSourceOver(overlay)(image)

    }

}

// 到现在为止,我们已经定义了模糊滤镜和颜色叠层滤镜,可以把它们组合在一起使用:首先将

// 图像模糊,然后再覆盖上一层红色叠层

let url = NSURL(string:"http://www.objc.io/images/covers/16.jpg")!

let image = CIImage(contentsOfURL:url)!


// 链式地将两个滤镜应用到载入的图像上

let blurRadius = 5.0

let overlayColor = NSColor.redColor().colorWithAlphaComponent(0.2)

let blurredImage = blur(blurRadius)(image)

let overlaidImage =colorOverlay(overlayColor)(blurredImage)



// 复合函数

//将上面代码里两个调用滤镜的表达式简单合为一体:可读性差

let result = colorOverlay(overlayColor)(blur(blurRadius)(image))


// 定义一个用于组合滤镜的函数

/**

composeFilters 函数接受两个 Filter类型的参数,并返回一个新定义的滤镜。

这个复合滤镜接 受一个 CIImage类型的图像参数,然后将该参数传递给

lter1,取得返回值之后再传递给lter2.可以使用复合函数来定义复合滤镜


*/

func composeFilters( lter1: Filter , _  lter2 : Filter ) -> Filter {

    return { image in  lter2 (  lter1 (image)) } }


let myFilter1 = composeFilters(blur(blurRadius),colorOverlay(overlayColor))

let result1 = myFilter1(image)



/// 为了让代码更具可读性,我们可以再进一步,为组合滤镜引入运算符。诚然,随意自定义运算

//符并不一定对提升代码可读性有帮助。不过,在图像处理库中,滤镜的组合是一个反复被讨论

//的问题,所以引入运算符极有意义

infix operator >>> {associativity left }

func >>> (  lter1 : Filter ,  lter2 : Filter ) -> Filter {

    return { image in  lter2 (  lter1 (image)) }

}


//与之前使用 composeFilters的方法相同,现在我们可以使用 >>>运算符达到目的:

//由于已经定义的运算符 >>>是左结合的 (left-associative),就像 Unix的管道一样,

//滤镜将以从左到右的顺序被应用到图像上

let myFilter2 = blur(blurRadius)>>> colorOverlay(overlayColor)

let result2 = myFilter2(image)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JS柯里是一种函数式编程的技术,由阮一峰在其博客中首次介绍。所谓柯里,就是将一个接受多个参数的函数转变为接受单一参数的函数序列的过程。 柯里的主要思想是延迟计算。通过柯里,可以将一个具有多个参数的函数转为一个接收单一参数的函数,这样的函数可以等到所有参数都准备好之后再进行计算。这样做的好处是可以将函数的使用更加灵活,调用的时候可以逐个传入参数,也可以一次性传入多个参数。另外,这样还可以用来创建一些固定部分参数的新函数,提高代码的复用性。 在JS中柯里可以通过函数递归的方式实现。函数递归地返回一个新函数,新函数可以保存已接收到的参数,并在接收新参数后进行计算和返回。因为JS的函数可以作为一等公民,可以作为参数和返回值,所以可以非常方便地实现柯里柯里在实际应用中非常有用。比如在函数式编程中,柯里可以用来创建高阶函数,可以根据传入的参数动态生成一个新的函数。另外,柯里还可以用来解决数据优先编程的问题,即将传入的数据先与函数返回的新函数结合,然后再进行计算。 总之,JS柯里是一种将多参数函数转为接收单一参数的函数序列的技术,可以通过函数递归实现。柯里的应用非常广泛,可以用于创建高阶函数和解决数据优先编程的问题。阮一峰在其博客中详细解释了柯里的概念和实现方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值