Swift 5.1 温故而知新笔记系列之第七天
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()
如果NSString
、NSMutableString
、String
都可以调用
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 温故而知新笔记系列之第七天相关推荐
- SpringBoot笔记系列目录
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过 ...
- SQL Server 2008/2012中SQL应用系列及BI学习笔记系列--目录索引
SQL Server 2008中的一些特性总结及BI学习笔记系列,欢迎与邀月交流. 3w@live.cn ◆0.SQL应用系列 1.SQL Server 2008中SQL增强之一:Values新用途 ...
- 《ASP.NET Core In Action》读书笔记系列五 ASP.NET Core 解决方案结构解析1
<ASP.NET Core In Action>读书笔记系列五 ASP.NET Core 解决方案结构解析1 参考文章: (1)<ASP.NET Core In Action> ...
- [老男孩笔记系列]-之linux定时任务crontab命令详解
linux定时任务crontab命令详解 1.1指令语法 crontab [ -u user ] file crontab [ -u user ] { -l | -r | -e } 1.2指令说明 通 ...
- BizTalk学习笔记系列之二:实例说明如何使用BizTalk
BizTalk学习笔记系列之二:实例说明如何使用BizTalk --.BizTalk学习笔记系列之二<?XML:NAMESPACE PREFIX = O /> Aaron.Gao,2006 ...
- NJ4X源码阅读分析笔记系列(一)——项目整体分析
NJ4X源码阅读分析笔记系列(一)--项目整体分析 NJ4X是什么 参见NJ4X的官网:http://www.nj4x.com/ Java and .Net interfaces to support ...
- SQLServer学习笔记系列2
SQLServer学习笔记系列2 一.写在前面的话 继上一次SQLServer学习笔记系列1http://www.cnblogs.com/liupeng61624/p/4354983.html以后,继 ...
- Hadoop学习笔记系列文章导航
一.为何要学习Hadoop? 这是一个信息爆炸的时代.经过数十年的积累,很多企业都聚集了大量的数据.这些数据也是企业的核心财富之一,怎样从累积的数据里寻找价值,变废为宝炼数成金成为当务之急.但数据增长 ...
- 《C#高级编程》笔记系列第一弹-开篇
虽然以前做过的C#项目也不少了,做过ASP.NET的BS架构的,也做过Winform的CS架构.有一天一位同事给我们看了下面的一个简单的Demo: public class MainTest ...
- Java基础复习笔记系列 九 网络编程
Java基础复习笔记系列之 网络编程 学习资料参考: 1.http://www.icoolxue.com/ 2. 1.网络编程的基础概念. TCP/IP协议:Socket编程:IP地址. 中国和美国之 ...
最新文章
- 大厂首发:kafka消费组订阅多个topic
- 4怎样判断动作是否执行_公众号交易时要怎样去判断粉丝是否真实的呢?
- 深入理解Spark 2.1 Core (十二):TimSort 的原理与源码分析
- spark出现task不能序列化错误的解决方法 org.apache.spark.SparkException: Task not serializable
- IntelliJ IDEA母公司JetBrains遭美国调查,其是美国被大规模黑客攻击的源头?
- Tushare在R中的使用
- linux 统计端口链接,linux netstat 统计链接数查看外部(转)
- Python 爬虫工具 —— fake_useragent
- Flutter报错 使用Column等容器包裹ListView报错的问题
- jQuery - 选择器(五)
- libjingle源码解析(3)-【PseudoTcp】建立UDP之上的TCP(1):连接和关闭
- 数字交易所内存撮合、无锁并发技术源码
- Linux系统编程:入门篇视频教程-王利涛-专题视频课程
- cat6 万兆_千兆网线和万兆网线有什么区别?
- deepin linux查看ip,deepin使用iproute配置网络命令
- 高频功率放大器输出为什么会有高次谐波
- WM_CTLCOLOR消息重载
- c代码实现 ifft运算_X^n+1=0上的FFT和IFFT(基2)——C语言实现
- 树莓派pico 最新固件地址以及无法进入BOOT模式(U盘挂载)解决方法
- php 函数索引 中文索引
热门文章
- 【OJ每日一练】1044 - 下落又弹起的小球
- 手写深度学习之优化器(SGD、Momentum、Nesterov、AdaGrad、RMSProp、Adam)
- 【WPS表格】数据透视表:统计各商品及各分店的销售总额
- YYC松鼠聚合直播系统添加图片上传视频提示网络错误的问题解决方案
- 将 SVN Repositories 内部的下层目录,提升成为顶层 Repositories 的风险
- mqtt 3.1 php代码,MQTT V3.1
- mongoDB 4.0 开启远程访问
- 实习期间的一些思考整理(4)2018.4.14~4.16
- 七、torch.nn
- ViewPager圆形指示器