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