Swift-Currying(柯里化)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数切返回结果的新函数的技术

1、什么是柯里化?



柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数切返回结果的新函数的技术


用数学理解就是:一个函数求xy,当传入y=2时,返回的就是2x


2、简单示例



例如:实现一个函数,输入的是任一整数,输出要返回输入的整数+2


一般的写法是

func addTwo(_ a : Int)->Int{
        return a+2
    }


上面这种写法就只是简单的可以实现这个函数,并没有进行优化,且不通用,里面的+2直接固定写死了,如果要实现+4/+6/+8,不能每次都去重新定义一个函数,我们需要定义一个通用的函数,所以需要做如下改进,主要利用的是swift的currying技术

func addTwo(_ a : Int)->(Int)->Int{
        return {b in
            return a+b
        }
    }

上面的函数可以简化成

func addTwo(_ a : Int)->(Int)->Int{
        return {b in a+b }
    }

还可以更通用一些,将参数定义为泛型

    //两个参数的泛型
    func curry<A, B>(_ function:@escaping (A)->B)->(A)->B{
        return {a in function(a)}
    }
    //三个参数的泛型
    func curry<A, B, C>(_ function:@escaping (A, B)->C)->(A)->(B)->C{
        return {a in {b in function(a,b)}}
    }
    //四个参数的泛型
    func curry<A, B, C, D>(_ function:@escaping (A, B, C)->D)->(A)->(B)->(C)->D{
        return {a in {b in {c in function(a, b, c)}}}
    }
    //currying调用
    func addTwo(_ a : Int, _ b : Int)->Int{
        return a+b
    }
    let result = curry(addTwo)(1)(2) //打印的结果为3


3、项目中的实际应用



主要应用在需要传多个参数的函数,


1)例如:假设有这样一个需求,我需要记录某个系统的日志,日志需要包含以下几个要素:操作人的名字name,时间time,日志类型type和日志内容msg。

    func curry<A, B, C, D, E>(_ function:@escaping (A, B, C, D)->E)->(A)->(B)->(C)->(D)->E{
        return {a in {b in {c in {d in function(a, b, c, d)}}}}
    }
    func createLogInfo(_ name : String, _ time : String, _ type : String, _ msg : String)->String{
        return "name : \(name)\n" + "type : \(type)\n" + ("message : \(msg)\n" + "time: \(time)    ")
    }
    //调用
    let createLogInfoResult = curry(createLogInfo)("functionName")("today")("Error")("somethingWrong")
输出结果:
name : functionName
type : Error
message : somethingWrong
time: today


2)封装target-action,对其安全的改造

原因:由于swift的selector智能是字符串生成,面临难以重构的问题,并且无法在编译期间检查


改造的步骤:


(1)定义一个目标事件协议

//目标事件协议
protocol TargetAction {
    func performAction()
}

(2)定义一个类,遵循(1)中的协议来处理事件

/**
 OC中的委托
 事件包装结构,这里是泛型,这里表示传入的数据类型可以是AnyObject
 这个方法遵循TargetAction协议来处理事件
 */
struct TargetActionWrapper<T: AnyObject>:TargetAction {
    weak var target : T?
    //柯里化
    let action : (T) -> () -> ()
    func performAction() {
        if let t = target {
            action(t)()
        }
    }
}

(3)枚举事件的类型

//枚举
enum ControlEvent{
    case TouchUpInside
    case ValueChanged
    //...
}

(4)示例

//示例
class currying{
    var actions = [ControlEvent : TargetAction]()
    func setTarget<T: AnyObject>(_ target : T, _ action : @escaping (T)->()->(), _ controlEvent : ControlEvent){
        actions[controlEvent] = TargetActionWrapper(target: target, action: action)
        print("T \(T.self)")
        print("action \(action)")
    }
    //移除
    func removeTargetForControlEvent(_ controlEvent : ControlEvent){
        actions[controlEvent] = nil
    }
    //执行
    func performActionForControlEvent(_ controlEvent : ControlEvent){
        actions[controlEvent]?.performAction()
    }
}

(5)在项目中的实际使用

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        currying().setTarget(self, ViewController.btnclick, .TouchUpInside)
    }
     func btnclick(){
        print("点击了")
    }
}


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
Swift
swift 学习笔记之在柯里化(Currying)
    有时候我们看到的方法中有很多组的参数,可能会让大家觉得疑惑,其实是因为这个方法使用了柯里化。
956 0
Swift 柯里化(Currying)
在计算机科学中,柯里化(英语:Currying),又譯為卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
1031 0
|
8月前
|
安全 编译器 Swift
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
463 2
|
6月前
|
Unix 调度 Swift
苹果iOS新手开发之Swift 中获取时间戳有哪些方式?
在Swift中获取时间戳有四种常见方式:1) 使用`Date`对象获取秒级或毫秒级时间戳;2) 通过`CFAbsoluteTimeGetCurrent`获取Core Foundation的秒数,需转换为Unix时间戳;3) 使用`DispatchTime.now()`获取纳秒级精度的调度时间点;4) `ProcessInfo`提供设备启动后的秒数,不表示绝对时间。不同方法适用于不同的精度和场景需求。
210 3
|
2月前
|
安全 Swift iOS开发
Swift 与 UIKit 在 iOS 应用界面开发中的关键技术和实践方法
本文深入探讨了 Swift 与 UIKit 在 iOS 应用界面开发中的关键技术和实践方法。Swift 以其简洁、高效和类型安全的特点,结合 UIKit 丰富的组件和功能,为开发者提供了强大的工具。文章从 Swift 的语法优势、类型安全、编程模型以及与 UIKit 的集成,到 UIKit 的主要组件和功能,再到构建界面的实践技巧和实际案例分析,全面介绍了如何利用这些技术创建高质量的用户界面。
46 2
|
2月前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户点击按钮时,按钮将从圆形变为椭圆形,颜色从蓝色渐变到绿色;释放按钮时,动画以相反方式恢复。通过UIView的动画方法和弹簧动画效果,实现平滑自然的过渡。
81 1
|
3月前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
【10月更文挑战第18天】本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户按下按钮时,按钮将从圆形变为椭圆形并从蓝色渐变为绿色;释放按钮时,动画恢复原状。通过UIView的动画方法和弹簧动画效果,实现平滑自然的动画过渡。
69 5
|
5月前
|
存储 移动开发 Swift
使用Swift进行iOS应用开发:探索现代移动开发的魅力
【8月更文挑战第12天】使用Swift进行iOS应用开发,不仅能够享受到Swift语言带来的简洁、快速、安全的编程体验,还能够充分利用iOS平台提供的丰富资源和强大功能。然而,iOS应用开发并非易事,需要开发者具备扎实的编程基础、丰富的实践经验和不断学习的精神。希望本文能够为您的iOS应用开发之旅提供一些有益的参考和帮助。
|
6月前
|
Swift iOS开发 Kotlin
苹果iOS新手开发之Swift中实现类似Kotlin的作用域函数
Swift可通过扩展实现类似Kotlin作用域函数效果。如自定义`let`, `run`, `with`, `apply`, `also`,增强代码可读性和简洁性。虽无直接内置支持,但利用Swift特性可达成相似功能。
85 7
|
6月前
|
调度 Swift Android开发
苹果iOS新手开发之Swift中的并发任务和消息机制
Swift的消息机制类似Android的Handler,实现任务调度有三种方式: 1. **Grand Central Dispatch (GCD)**:使用`DispatchQueue`在主线程或后台线程执行任务。 2. **OperationQueue**:提供高级接口管理`Operation`对象。 3. **RunLoop**:处理事件如输入源、计时器,类似Android的`Looper`和`Handler`。 **示例**: - GCD:在不同线程执行代码块。 - OperationQueue:创建操作并执行。 - RunLoop:用Timer添加到RunLoop中。
117 2