函数式编程的前世今生

函数式编程的前世今生

一等函数的理念可以追溯到 Church 的 lambda 演算 (Church 1941; Barendregt
1984)。此后,包括 Haskell,OCaml,Standard ML,Scala 和 F# 在内的大量 (函数式) 编程语言都不同程度地借鉴了这个概念。


OC中的一等函数 是 blocks

Swift 中就是闭包

尽管在语义上oc和swift的一等函数 完全相同,但swift的语法更加简单,使用更加方便。

例子

//  hFilter.swift
//  hRACDemo
//
//  Created by Admin on 2016/9/20.
//  Copyright © 2016年 侯迎春. All rights reserved.
//

/**
 *  hFilter        CoreImage 滤镜相关
 *  API 介绍
 *  CIImage        图像配置
 *  kCIInput..     图像处理的来源键值
 *  filter         图像处理 通过处理的名字 和图像来源数据
 *  outputImage    输出经过图像处理的图像配置源
 */

import UIKit

// 一等函数 也是一个闭包  CIImage = 图像配置
typealias hFilter = (CIImage) -> CIImage

var hycblock : (()->())?
// 模糊效果  高斯模糊
func hBlur(radius:Double) -> hFilter {
    return { image in
        let parameters = [kCIInputRadiusKey: radius,
                          kCIInputImageKey : image] as [String : AnyObject]

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

        return outputImage;

    }
}


// Core Image 默认不包含这样一个滤 镜,但是我们完全可以用已经存在的滤镜来组成它。
// 我们将使用的两个基础组件:颜色生成滤镜 (CIConstantColorGenerator) 和图像覆盖合成滤镜 (CISourceOverCompositing)。首先让我们来定义一个生成固定颜色的滤镜
// 颜色叠层
func hColorGennerator(Color color:UIColor) -> hFilter {
    return { _ in

        guard let newColor : CIColor = CIColor.init(color: color) else {fatalError()}
        let paramters = [kCIInputColorKey: newColor]

        guard let filter = CIFilter.init(name: "CIConstantColorGenerator", withInputParameters: paramters) else{fatalError()}

        guard let outputImage = filter.outputImage else {fatalError()}

        return outputImage
    }
}


//这段代码看起来和我们用来定义模糊滤镜的代码非常相似,但是有一个显著的区别:颜色生成 滤镜不检查输入图像。因此,我们不需要给返回函数中的图像参数命名。取而代之,我们使用 一个匿名参数 _ 来强调滤镜的输入图像参数是被忽略的。
//接下来,我们将要定义合成滤镜:
func compositeSourceOver(overlay: CIImage) -> hFilter { return { image in
    let parameters = [ kCIInputBackgroundImageKey: image, kCIInputImageKey: overlay
    ]
    guard let  lter = CIFilter (name: "CISourceOverCompositing",
                                withInputParameters: parameters) else { fatalError() }
    guard let outputImage =  lter.outputImage else { fatalError() }
    let cropRect = image.extent
    return outputImage.imageByCroppingToRect(cropRect)
    }
}



//在这里我们将输出图像剪裁为与输入图像一致的尺寸。严格来说,这不是必须的,而完全取决
//于我们希望滤镜如何工作。不过,这个选择在我们即将涉及的例子中效果很好。
//最后,我们通过结合两个滤镜来创建颜色叠层滤镜:
func colorOverlay(color:UIColor)->hFilter {
    return { image in
        let overlay = hColorGennerator(Color: color)(image)
        return compositeSourceOver(overlay)(image)
    }
}
//我们再次返回了一个接受图像作为参数的函数。colorOverlay 函数首先调用了 colorGenerator 滤镜。colorGenerator 滤镜需要一个 color 作为参数,然后返回一个新的滤镜,因此代码片段
//colorGenerator(color) 是 Filter 类型。而 Filter 类型本身就是一个从 CIImage 到 CIImage 的 函数;因此我们可以向 colorGenerator(color) 函数传递一个附加的 CIImage 类型的参数,最终 我们能够得到一个 CIImage 类型的新叠层。这就是我们在定义 overlay 的过程中所发生的全部 事情事,可以大致概括为 —— 首先使用 colorGenerator 函数创建一个滤镜,接着向这个滤镜 传递一个 image 参数来创建新图像。与之类似,返回值 compositeSourceOver(overlay)(image) 由一个通过 compositeSourceOver(overlay) 函数构建 的滤镜和随即被作为参数的 image 组成。



//复合函数
//当然,我们可以两个调用滤镜的表达式简单合为一体:
//let result = colorOverlay(overlayColor)(blur(blurRadius)(image)) 然而,由于括号错综复杂,这些代码很快失去了可读性。更好的解决方式是自定义一个运算符来组合滤镜。为了定义该运算符,首先我们要定义一个用于组合滤镜的函数:
func composeFilters( lter1: hFilter , _  lter2 : hFilter ) -> hFilter {
    return { image in  lter2 (  lter1 (image)) } }
//composeFilters 函数接受两个 Filter 类型的参数,并返回一个新定义的滤镜。这个复合滤镜接 受一个 CIImage 类型的图像参数,然后将该参数传递给  lter1,取得返回值之后再传递给  lter2。我们可以使用复合函数来定义复合滤镜,就像下面这样:
//let myFilter1 = composeFilters(blur(blurRadius), colorOverlay(overlayColor)) let result1 = myFilter1(image)
//为了让代码更具可读性,我们可以再进一步,为组合滤镜引入运算符。诚然,随意自定义运算
//符并不一定对提升代码可读性有帮助。不过,在图像处理库中,滤镜的组合是一个反复被讨论
//的问题,所以引入运算符极有意义:

infix  operator >>> { associativity left }
func >>> (  lter1 : hFilter ,  lter2 : hFilter ) -> hFilter { return { image in  lter2 (  lter1 (image)) }
}
//与之前使用 composeFilters 的方法相同,现在我们可以使用 >>> 运算符达到目的:
//let myFilter2 = blur(blurRadius) >>> colorOverlay(overlayColor) let result2 = myFilter2(image)
//由于已经定义的运算符 >>> 是左结合的 (left-associative),就像 Unix 的管道一样,滤镜将以从 左到右的顺序被应用到图像上。
//我们定义的组合滤镜运算符是一个复合函数的例子。在数学中,f 和 g 两个函数构成的复合函 数有时候被写作 f · g,表示定义的新函数将输入的 x 映射到 f(g(x))。除了顺序,这恰恰也是 我们的 >>> 运算符所做的:将一个图像参数传递给运算符操作的两个滤镜。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值