如何将一个接受多参数的函数变换为一系列只接受单个参数的函数,这个过程被称为柯里化 (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)

swift 柯里化的更多相关文章

  1. swift 学习笔记之在柯里化Currying

    有时候我们看到的方法中有很多组的参数,可能会让大家觉得疑惑,其实是因为这个方法使用了柯里化。现在result的结果是3。柯里化的好处是提供了一个模板,可以写出具有很高复用性的代码,比如上例可以指定一个运算数建立一套方法。

  2. Swift 新特性之柯里化函数

    前言此次文章,讲述的是Swift的一个新特性,可能很多iOS开发人员是第一次听这个词汇,包括我自己也是,自己也用了几天时间才总结出来,希望能帮助到各位咯,个人感觉偏向有开发经验的码友,如果零基础的看懂,希望能给个赞!什么是柯里化函数?important;font-family:Consolas,返回值为Int类型的函数functionC=functionB//result:函数的返回值res=functionC//打印60,60,60说明手动实现的柯里化函数,和系统的一样。

  3. Currying-柯里化[Swift笔记]

    Currying(柯里化)是什么?

  4. Swift中实例方法柯里化及自己实现Target-action模式

    但是target-action又是Cocoa中如此重要的一种设计模式,无论如何我们都想安全地使用的话,应该怎么办呢?OleBegemann在这篇帖子里提到了一种很好封装,这为我们如何借助柯里化,安全地改造和利用target-action提供了不少思路。示例二Swift中实现Target-ActionChristofferLern在开发者论坛上展示了如何使用纯swift语言将Swift的类型系统这一特点应用到target-action模式中。使用target-action模式,提供API的对象可以做内部类型

  5. Swift中的实例方法--柯里化方法(Curried Functions)

    Swift中的实例方法–柯里化方法声明:本文为本人翻译自国外的一片文章,英文水平有限,还望大家不吝赐教。注意方法二中BankAccount.deposit后面没有小括号,所以在这里我们并没有调用方法,只是对它的一个引用。在第二部分中你应该意识到实例方法deposit()的签名。当然,我们也可以把这些放在一行,这使得类型方法和实例方法之间的关系更加清晰:通过实例BankAccount.deposit(),被绑定到实例函数。

  6. Swift中的柯里化Currying

    什么是柯里化首先,我们来看个简单的例子:这个函数很容易理解,就是一个整型求和的函数,函数接收两个整型作为参数,并返回两个参数相加的结果。进一步理解柯里化我们看看下面的简单实例:我们最常见的用法:下面看一个非常规的用法:我们看见下面的操作实现的效果于上面的那个是一样的。熟悉了解柯里化的特性后,以后就可以自己写个高复用的类库了,当然也可以使用上篇文章中提到的Curry类库

  7. Swift函数柯里化(Currying)简谈

    这样不仅不优雅而且容易把新手绕晕,于是我们把函数摇身一变:柯里化思密达:我们这样调用:注意,以上函数的写法貌似返回类型是Spider,其实不然!

  8. swift 柯里化

    取而代之,我们使用一个匿名参数_来强调滤镜的输入图像参数是被忽略的*/funccolorGenerator->Filter{return{_inguardletc=CIColorelse{fatalError()}letparameters=[kCIInputColorKey:c]guardletlter=CIFilterelse{fatalError()}guardletoutputimage=lter.outputimageelse{fatalError()}returnoutputimage}}定义

  9. Swift Currying柯里化

    SwiftCurrying(柯里化)标签:swift函数式编程思想先举一个小例子:显然这种编程方式更加灵活,所展现的内容更加直观,可以减少函数写N多的参数;当然函数式编程有的可不只是这些,更多内容不在本篇所讨论之内;基于上例我们来写一个方法:很明显下面这个式子的调用直观的表达了参数10和参数11的大小;target-action例子我们来看国外网上的一个例子:

  10. JavaScript函数柯里化详解

    这篇文章主要为大家介绍了JavaScript函数柯里化,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部