1.函数式编程

函数式编程(Funtional Programming,简称FP)是一种编程范式,也就是如何编写程序的方法论

  • 主要思想:把计算过程尽量分解成一系列可复用函数的调用
  • 主要特征:函数是“第一等公民”
  • 函数与其他数据类型一样的地位,可以赋值给其他变量,也可以作为函数参数、函数返回值

示例一

传统写法

//[(num + 3) * 5 - 1] % 10 / 2
func add(_ v1: Int, _ v2: Int) -> Int{ v1 + v2 }
func sub(_ v1: Int, _ v2: Int) -> Int{ v1 - v2 }
func multiple(_ v1: Int, _ v2: Int) -> Int{ v1 * v2 }
func divide(_ v1: Int, _ v2: Int) -> Int{ v1 / v2 }
func mod(_ v1: Int, _ v2: Int) -> Int{ v1 % v2 }var num: Int = 1print(divide(mod(sub(multiple(add(num, 3), 5), 1), 10), 2))

函数式

// 中缀运算符
//infix operator >>> : AdditionPrecedence
//func >>> (_ v1: Int, _ v2: Int) -> Int{//    return v1 + v2
//}
//
//var num1 = 20
//var num2 = 30
 50
//print(num1 >>> num2)// [(num + 3) * 5 - 1] % 10 / 2
func add(_ v: Int) -> (Int) -> Int { {$0 + v} }
func sub(_ v: Int) -> (Int) -> Int { {$0 - v} }
func multiple(_ v: Int) -> (Int) -> Int { {$0 * v} }
func divide(_ v: Int) -> (Int) -> Int { {$0 / v} }
func mod(_ v: Int) -> (Int) -> Int { {$0 % v} }infix operator >>> : AdditionPrecedence
func >>><A,B,C>(_ f1: @escaping (A) -> B,_ f2: @escaping (B) -> C) -> (A) -> C { { f2(f1($0)) } }var fn = add(3) >>> multiple(5) >>> sub(1) >>> mod(10) >>> divide(2)
print(fn(1))

高阶函数

  • 接受一个或者多个函数作为输入(map,filter,reduce)
  • 作为返回值

柯里化

  • 将一个接受多参数的函数变换为一系列只接受单个参数的函数

手动柯里化

// 两个参数柯里化
func sub1(_ v1: Int, _ v2: Int) -> Int { v1 - v2 }print(sub1(10,20))func sub1(_ v1: Int) -> (Int) -> Int {return {v2 inreturn v1 - v2}
}print(sub1(10)(20))// 三个参数柯里化
func sub3(_ v1: Int, _ v2: Int, _ v3: Int) -> Int { v1 - v2 - v3 }
print(sub3(10, 20, 30))func sub4(_ v1: Int) -> (Int) -> (Int) -> Int {return { v2 inreturn { v3 inreturn v1 - v2 - v3}}
}print(sub4(10)(20)(30))

通用柯里化


func sub1(_ v1: Int, _ v2: Int) -> Int { v1 - v2 }func sub2(_ v1: Int, _ v2: Int, _ v3: Int) -> Int { v1 - v2 - v3 }prefix func ~<A, B, C>(_ fn: @escaping (A, B) -> C) -> (B) -> (A) -> C {{ b in { a in fn(a, b) } }
}prefix func -<A, B, C, D>(_ fn: @escaping (A, B, C) -> D) -> (C) -> (B) -> (A) -> D {{ c in { b in { a in fn(a, b, c)} } }
}print(sub1(20, 10))
print((~sub1)(10)(20))print(sub2(10,20,30))
print((-sub2)(30)(20)(10))// [(num + 3) * 5 - 1] % 10 / 2func add(_ v1: Int, _ v2: Int) -> Int{ v1 + v2 }
func sub(_ v1: Int, _ v2: Int) -> Int{ v1 - v2 }
func multiple(_ v1: Int, _ v2: Int) -> Int{ v1 * v2 }
func divide(_ v1: Int, _ v2: Int) -> Int{ v1 / v2 }
func mod(_ v1: Int, _ v2: Int) -> Int{ v1 % v2 }infix operator >>> : AdditionPrecedence
func >>><A,B,C>(_ f1: @escaping (A) -> B,_ f2: @escaping (B) -> C) -> (A) -> C { { f2(f1($0)) } }
var fn = (~add)(3) >>> (~multiple)(5) >>> (~sub)(1) >>> (~mod)(10) >>> (~divide)(2)
print(fn(1))

2. 面向协议编程

  • 优先考虑创建协议(接口),而不是父类(基类)
  • 优先考虑值类型(struct,enum),而不是引用类型(class),结构体不能被继承,而且接口体的调用方式比引用类型简单,被迫使用接口的方式编程
  • Swift支持协议扩展
  • 不要为了面向协议而面向协议

2.1 示例1

class Person {var name: Stringvar age: Intinit(_ name: String, _ age: Int) {self.name = nameself.age = age}
}struct MK<T> {var base: Tinit(_ base: T) {self.base = base}
}extension String {var mk: MK<String> { MK(self) }static var mk: MK<String>.Type { MK<String>.self }
}
extension MK where T == String {var stringCount: Int {var count = 0for c in self.base where ("0"..."9").contains(c){count += 1}return count}static func run() {print("static run")}
}extension Person {var mk: MK<Person> { MK(self) }static var mk: MK<Person>.Type { MK<Person>.self }
}extension MK where T : Person{var personName: String {return self.base.name}
}var str1: String = "MIke2345jing123"print(str1.mk.stringCount)
String.mk.run()var person = Person("Miqishu", 3)
print(person.mk.personName)

抽象之后

class Person {var name: Stringvar age: Intinit(_ name: String, _ age: Int) {self.name = nameself.age = age}
}class Student: Person {}struct MK<T> {var base: Tinit(_ base: T) {self.base = base}
}protocol MKCompatiable {}
extension MKCompatiable{var mk: MK<Self> {get {MK(self)}set {}}static var mk: MK<Self>.Type {get {MK<Self>.self}set {}}
}extension String : MKCompatiable {}
extension MK where T == String {var stringCount: Int {var count = 0for c in self.base where ("0"..."9").contains(c){count += 1}return count}static func run() {print("static run")}
}extension Person : MKCompatiable {}
extension MK where T : Person{var personName: String {return self.base.name}static func study() {print("static study")}
}var str1: String = "MIke2345jing123"print(str1.mk.stringCount)
String.mk.run()var person = Person("Miqishu", 3)
print(person.mk.personName)var stu = Student("jiaojiao", 10)
Student.mk.study()

如果NSStringNSMutableStringString都可以调用


var s1: String = "12345453534dsfsfsd"
var s2: NSString = "sa12312sdsds"
var s3: NSMutableString = "3123dsfsdf23"
print(s1.mk.stringCount)
print(s2.mk.stringCount)
print(s3.mk.stringCount)extension String : MKCompatiable {}
extension NSString : MKCompatiable {}
extension MK where T : ExpressibleByStringLiteral {var stringCount: Int {var count = 0for c in self.base as! String where ("0"..."9").contains(c){count += 1}return count}static func run() {print("static run")}
}

2.2 示例2

利用协议实现类型判断


func isArray(_ value: Any) -> Bool {value is [Any]
}print(isArray([1,2])) // true
print(isArray(["1",2])) // true
print(isArray(NSArray())) // true
print(isArray(NSMutableArray())) // trueprotocol ArrayType {}
extension Array : ArrayType{}
extension NSArray : ArrayType{}
func isArrayType(_ type: Any.Type) -> Bool {type is ArrayType.Type}
print(isArrayType([Int].self)) // true
print(isArrayType([Any].self)) // true
print(isArrayType(NSArray.self)) // true
print(isArrayType(NSMutableArray.self))  // true

Swift 5.1 温故而知新笔记系列之第七天相关推荐

  1. SpringBoot笔记系列目录

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过 ...

  2. SQL Server 2008/2012中SQL应用系列及BI学习笔记系列--目录索引

    SQL Server 2008中的一些特性总结及BI学习笔记系列,欢迎与邀月交流. 3w@live.cn  ◆0.SQL应用系列 1.SQL Server 2008中SQL增强之一:Values新用途 ...

  3. 《ASP.NET Core In Action》读书笔记系列五 ASP.NET Core 解决方案结构解析1

    <ASP.NET Core In Action>读书笔记系列五 ASP.NET Core 解决方案结构解析1 参考文章: (1)<ASP.NET Core In Action> ...

  4. [老男孩笔记系列]-之linux定时任务crontab命令详解

    linux定时任务crontab命令详解 1.1指令语法 crontab [ -u user ] file crontab [ -u user ] { -l | -r | -e } 1.2指令说明 通 ...

  5. BizTalk学习笔记系列之二:实例说明如何使用BizTalk

    BizTalk学习笔记系列之二:实例说明如何使用BizTalk --.BizTalk学习笔记系列之二<?XML:NAMESPACE PREFIX = O /> Aaron.Gao,2006 ...

  6. NJ4X源码阅读分析笔记系列(一)——项目整体分析

    NJ4X源码阅读分析笔记系列(一)--项目整体分析 NJ4X是什么 参见NJ4X的官网:http://www.nj4x.com/ Java and .Net interfaces to support ...

  7. SQLServer学习笔记系列2

    SQLServer学习笔记系列2 一.写在前面的话 继上一次SQLServer学习笔记系列1http://www.cnblogs.com/liupeng61624/p/4354983.html以后,继 ...

  8. Hadoop学习笔记系列文章导航

    一.为何要学习Hadoop? 这是一个信息爆炸的时代.经过数十年的积累,很多企业都聚集了大量的数据.这些数据也是企业的核心财富之一,怎样从累积的数据里寻找价值,变废为宝炼数成金成为当务之急.但数据增长 ...

  9. 《C#高级编程》笔记系列第一弹-开篇

    虽然以前做过的C#项目也不少了,做过ASP.NET的BS架构的,也做过Winform的CS架构.有一天一位同事给我们看了下面的一个简单的Demo:     public class MainTest ...

  10. Java基础复习笔记系列 九 网络编程

    Java基础复习笔记系列之 网络编程 学习资料参考: 1.http://www.icoolxue.com/ 2. 1.网络编程的基础概念. TCP/IP协议:Socket编程:IP地址. 中国和美国之 ...

最新文章

  1. 大厂首发:kafka消费组订阅多个topic
  2. 4怎样判断动作是否执行_公众号交易时要怎样去判断粉丝是否真实的呢?
  3. 深入理解Spark 2.1 Core (十二):TimSort 的原理与源码分析
  4. spark出现task不能序列化错误的解决方法 org.apache.spark.SparkException: Task not serializable
  5. IntelliJ IDEA母公司JetBrains遭美国调查,其是美国被大规模黑客攻击的源头?
  6. Tushare在R中的使用
  7. linux 统计端口链接,linux netstat 统计链接数查看外部(转)
  8. Python 爬虫工具 —— fake_useragent
  9. Flutter报错 使用Column等容器包裹ListView报错的问题
  10. jQuery - 选择器(五)
  11. libjingle源码解析(3)-【PseudoTcp】建立UDP之上的TCP(1):连接和关闭
  12. 数字交易所内存撮合、无锁并发技术源码
  13. Linux系统编程:入门篇视频教程-王利涛-专题视频课程
  14. cat6 万兆_千兆网线和万兆网线有什么区别?
  15. deepin linux查看ip,deepin使用iproute配置网络命令
  16. 高频功率放大器输出为什么会有高次谐波
  17. WM_CTLCOLOR消息重载
  18. c代码实现 ifft运算_X^n+1=0上的FFT和IFFT(基2)——C语言实现
  19. 树莓派pico 最新固件地址以及无法进入BOOT模式(U盘挂载)解决方法
  20. php 函数索引 中文索引

热门文章

  1. 【OJ每日一练】1044 - 下落又弹起的小球
  2. 手写深度学习之优化器(SGD、Momentum、Nesterov、AdaGrad、RMSProp、Adam)
  3. 【WPS表格】数据透视表:统计各商品及各分店的销售总额
  4. YYC松鼠聚合直播系统添加图片上传视频提示网络错误的问题解决方案
  5. 将 SVN Repositories 内部的下层目录,提升成为顶层 Repositories 的风险
  6. mqtt 3.1 php代码,MQTT V3.1
  7. mongoDB 4.0 开启远程访问
  8. 实习期间的一些思考整理(4)2018.4.14~4.16
  9. 七、torch.nn
  10. ViewPager圆形指示器