函数类型与闭包

函数类型

  • 函数类型定义:(参数类型1,参数类型2,……)->返回值类型
  • 函数类型是一种引用类型,类似于函数指针。可以将函数类型应用于任何使用类型的地方:变量、参数、返回值。
  • 函数类型实例化支持:
    • 全局函数
    • 嵌套函数
    • 成员函数(实例方法 与 静态方法)
func add(x:Double, y:Double)->Double{
  return x+y
}

func minus(x:Double, y:Double)->Double{
  return x-y
}

func mulitiply(x:Double, y:Double)->Double{
  return x*y
}

func divide(x:Double,y:Double)->Double{
  return x/y
}

class Matrix{
  var row=0.0
  var column=0.0

  init(row:Double ,colomn:Double){
    self.row=row
    self.column=column
}

  func process(x:Double, y:Double)->Double{
    return x*row+y*column
}
  
  static func invoke(x:Double, y:Double)->Double{
    return x*y+y*y
}
}
//函数类型作为变量
var compute:(Double, Double)->Double

compute=add //全局函数
let result1=compute(100,200)

compute=divide
let result2=compute(300,40)

var matrix=Matrix(row:10.0,column:20.0)
compute=matrix.process //实例方法
//compute.object=matrix
//compute.method=&process
compute(80,60)//JMP  compute.method

compute=Matrix.invoke //静态方法
compute(30,40)

//函数类型作为参数
func process(math: (Double,Double)->Double,x:double,y:Double){
  let result=math(x,y)
  print("result:\(result)")  
}

process(multiply,x:30,y:50)

//函数类型作为返回值
func calculateFunction(symbol:String)->(Double,Double)->Double{
  switch(symbol){
  case "+":
           return add
  case "-":
           return minus
  case "*":
           return multiply
  case "/":
           return divide
  default:
      return add
  }
}

var calculate=calculateFunction("-")
let result3 = calculate(300,80)

//嵌套函数
func algorithmFunction(symbol:String)-> (Double, Double)->Double{
  func add(x:Double, y:Double)->Double{
    return x+y
  }

  func minus(x:Double, y:Double)->Double{
    return x-y
  }

  func mulitiply(x:Double, y:Double)->Double{
    return x*y
  }

  func divide(x:Double,y:Double)->Double{
    return x/y
  }
  switch(symbol){
    case "+":
           return add
    case "-":
           return minus
    case "*":
           return multiply
    case "/":
           return divide
    default:
      return add
  }
}

var algorithm=algorithmFuntion("/")
let result4 = algorithm(600,80)
函数类型的内存模型.png

compute=全局函数时,对象指针为空
认识闭包Closure
=====================

  • 闭包是函数类型的实例,一段自包含的代码块,可被用于函数类型的变量,参数或返回值。

  • 三种闭包形式:

    • 全局函数:具名函数,但不捕获任何值
    • 嵌套函数:在函数内部嵌套定义具名函数,可捕获包含函数中的值
    • 闭包表达式:匿名函数类型实例,不具名的代码块,可捕获上下文中的值
  • 闭包是引用类型,闭包变量拷贝具有引用语义。

  • 闭包和函数类型实例拥有同样的内存模型。

class Rectangle {
  var width=0
  var length=0

  init(width:Int, length:Int){
    self.width=width
    self.length=length
  }
}

func <= (left: Rectangle, right: Rectangle) -> Bool {
  return left.width*left.length<=right.width*right.length
}

func compare(first:Rectangle, second: Rectangle)->Bool{
  return first.width*first.length<=second.width*second.length
}

var rects = [Rectangle(width:6,length:7),
             Rectangle(width:5,length:8),
             Rectangle(width:9,length:6)]

//函数类型对象
/*
func sort(@noescape isOrderedBefore: (Self.Generator.Element,Self.Generator.Element) -> Bool) -> [Self.Generator.Element]
*/
//func sort(isOrderedBefore:(Rectangle,Rectangle)->Bool)->[Rectangle]

var predict:  (Rectangle,Rectangle)->Bool
predict=compare
rects.sort(predict)

rects.sort(compare) //不用上面那样绕


//闭包表达式
rects.sort({(first:Rectangle, second:Rectangle)->Bool in

  return first.width*first.length<=second.width*second.length
})


let expression={(first:Rectangle, second:Rectangle)->Bool in
  return first.width*first.length<=second.width*second.length
}
rects.sort(exprssion)//也可以这么写

//自动类型推断
rects.sort({first,second in
  return first.width*first.length<=second.width*second.length
})

//单表达式省略return
rects.sort({first,second in first.width*first.length<=second.width*second.length})

//参数缩略形式
rects.sort({$0.width*$0.length<=$1.width*$1.length})

//操作符缩略式
rects.sort( <= ) //rects.sort(compare)

//尾随闭包
rects.sort{
  first,second in
  first.width*first.length<=second.width*second.length
}

rects.sort{$0.width*$0.length<=$1.width*$1.length}

//自动闭包
var cities = ["Beijing","shanghai","New York","Paris","London"]
print(cities.count)

let filter = {cities.removeLast()}//()->String
print(cities.count)

print("Deleting\(filter())!")
print(cities.count)

闭包表达式

{(参数1,参数2……)->返回值类型 in
语句块
}

  • 几种简化缩写形式:
    • 自动类型推断:省略参数类型和返回值类型
    • 单表达式闭包可以省去return关键词。
    • 使用参数缩略形式$0,$1...省略参数声明和in
    • 将操作符函数自动推导为函数类型
    • 尾随闭包:当闭包表达式为函数最后一个参数,可将其写在括号后
    • 自动闭包:不接受任何参数,直接返回表达式的值。允许延迟计算

函数类型与闭包的变量捕获

  • 函数类型和闭包可以捕获其所在上下文的任何值:

    • 函数参数
    • 局部变量
    • 对象实例属性
    • 全局变量
    • 类的类型属性
  • 如果捕获值生存周期小于闭包对象(参数和局部变量),系统会将被捕获的值封装在一个临时对象里,然后在闭包对象上创建一个对象指针,指向该临时对象。

  • 临时对象和闭包对象之间是强引用关系,生存周期跟随闭包对象。

var data=100

//捕获实例属性
class Rectangle{
  var width=0
  var length=0

  static var max=100

  init(width:Int,length:Int){
    self.width=width
    self.length=length
  }

  func getComputeHandler()->() -> Int{
    return {
      return self.width*self.length
    }
  }
}
var rect=Rectangle(width:10,length:20)
var handler=rect.getComputeHandler()
handler()

//捕获参数或局部变量
func addHandler(var step: Int) -> () -> Int {
  var sum = 0
  return {
    sum += step
    data++
    Rectangle.max++
    step++
    return sum
  }
/*  func add() ->Int {
    sum+=step

    return sum  
  }
  return add*/
  
}
let addByTen=addHandler(10)

addByTen()
addByTen()
addByTen()
print(data)
print(Rectangle.max)

let addBYSix=addHandler(6)

addBySix()
addBySix()
addBySix()
print(data)
print(Rectangle.max)

/*class AddHelper {
  var sum=0
  var step=0

  func add() -> Int {
    self.sum+=self.step
    return self.sum
  }
}

func addHandlerHelper(step: Int) -> () -> Int {
  let sum=0
  let obj=AddHelper()
  obj.sum=sum
  obj.step=step
  let closuer=obj.add
  return closuer
}

let addByTen=addHandlerHelper(10)

print(addByTen())
print(addByTen())
print(addByTen())

let addByTen=addHandlerHelper(6)

print(addBySix())
print(addBySix())
print(addBySix())*/
捕获值的内存模型.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容

  • 本章将会介绍 闭包表达式尾随闭包值捕获闭包是引用类型逃逸闭包自动闭包枚举语法使用Switch语句匹配枚举值关联值原...
    寒桥阅读 1,559评论 0 3
  • 86.复合 Cases 共享相同代码块的多个switch 分支 分支可以合并, 写在分支后用逗号分开。如果任何模式...
    无沣阅读 1,364评论 1 5
  • 闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代...
    莽原奔马668阅读 1,885评论 2 12
  • 七百里迢迢 我从凤凰花开的雨季走来 听说这里的人好客 但我不是客 只是无意中来到了你的小城 一把伞里孤独的影 看花...
    深海暖阳光阅读 256评论 0 0
  • CALayer contents属性 CALayer有一个属性叫做contents,这个属性是id类型,可以接收任...
    繁华落尽丶lee阅读 556评论 0 1