func testFunc() {
print("test method")
}
func makeIncrementer() -> () -> Int {
var runningTotal = 10
func incrementer() -> Int{
runningTotal += 1
return runningTotal
}
return incrementer
}
var t = { (age:Int) in
return age
}
let b = t(20)
print(b) // 20
{ (parameters) -> return type in
statements
}
// 此处参数为Int类型 -> 返回值类型也为Int
var a = { (param:Int) -> Int in
return param+1
}
var closure:((Int) -> Int)?
closure = { (param:Int) -> Int in
return param+1
}
print(closure?(10) ?? 0)//11
closure = nil //可置空
//由于当前的闭包表达式被定义为变量、所以赋值之后还可以再次更改。如果为let则不可再次更改
closure = { (param:Int) -> Int in
return param * param
}
print(closure?(10) ?? 0)//100
func closureTest(param:() -> Int){
print(param()) //25
}
var age:Int = 20
closureTest { () -> Int in //尾随闭包
age+=5
return age
}
func closureAfter(_ a: Int, _ b: Int, _ c: Int, by: (_ item1: Int, _ item2: Int, _ item3: Int) -> Bool) -> Bool{
return by(a, b, c)
}
closureAfter(10, 20, 30,by:{ (_ item1:Int, _ item2:Int, _ item3:Int) -> Bool in
return item1 + item2 < item3
})
closureAfter(10, 20, 30){ (_ item1:Int, _ item2:Int, _ item3:Int) -> Bool in
return item1 + item2 < item3
}
1、省略参数类型
closureAfter(10, 20, 30) { (item1, item2, item3) -> Bool in
return item1 + item2 < item3
}
2、省略by参数闭包的返回值
closureAfter(10, 20, 30) { (item1, item2, item3) in
return item1 + item2 < item3
}
3、省略 return 关键字
closureAfter(10, 20, 30) { (item1, item2, item3)in
item1 + item2 < item3
}
4、省略参数名称及 in、使用 $0、$1、$2来表示参数
closureAfter(10, 20, 30) { return $0 + $1 < $2 }
5、继续省略 return关键字
closureAfter(10, 20, 30) { $0 + $1 < $2}
var array = [1,2,4,3,0]
array = array.sorted(by: <)
print(array) //[0, 1, 2, 3, 4]
func makeIncrementer() -> () -> Int {
var runningTotal = 10
func incrementer() -> Int{
runningTotal += 1
return runningTotal
}
return incrementer
}
let makeInc = makeIncrementer()//将返回函数传给常量 makeInc
print(makeInc()) //11
print(makeInc()) //12
print(makeInc()) //13
//然而直接调用三次的结果却为
print(makeIncrementer()()) //11
print(makeIncrementer()()) //11
print(makeIncrementer()()) //11
结果为什么不一样呢?这里我们引入捕获值
// makeIncrementer()
sil hidden @main.makeIncrementer() -> () -> Swift.Int : $@convention(thin) () -> @owned @callee_guaranteed () -> Int {
bb0: //alloc_box 创建一个变量给我们当前的变量 runningTotal、相当于把一个引用地址给了我们的 runningTotal,意味着当前的变量放到了我们当前的堆上
%0 = alloc_box ${ var Int }, var, name "runningTotal" // users: %8, %7, %6, %1
//project_boc取出创建好的这个变量
%1 = project_box %0 : ${ var Int }, 0 // user: %4
%2 = integer_literal $Builtin.Int64, 10 // user: %3
%3 = struct $Int (%2 : $Builtin.Int64) // user: %4
store %3 to %1 : $*Int // id: %4
// function_ref incrementer #1 () in makeIncrementer()
//在调用过程中、这个创建好的变量就传递给了我们的闭包来使用
%5 = function_ref @incrementer #1 () -> Swift.Int in main.makeIncrementer() -> () -> Swift.Int : $@convention(thin) (@guaranteed { var Int }) -> Int // user: %7
//闭包调用开始、对这个对象做了强引用计数+1操作
strong_retain %0 : ${ var Int } // id: %6
//闭包调用过程
%7 = partial_apply [callee_guaranteed] %5(%0) : $@convention(thin) (@guaranteed { var Int }) -> Int // user: %9
//对这个对象做了强引用计数的-1操作
strong_release %0 : ${ var Int } // id: %8
return %7 : $@callee_guaranteed () -> Int // id: %9
} // end sil function 'main.makeIncrementer() -> () -> Swift.Int'
综上总结:
func makeIncrementer() -> () -> Int {
var runningTotal = 10
func incrementer() -> Int{
runningTotal += 1
return runningTotal
}
return incrementer
}
let makeInc = makeIncrementer()
print(makeInc())
(lldb) po makeInc
(Function)
iN //N位的整型值
i1 //一位整数。
i8 //一个8位的整型:也就是1字节
i32 //一个32位整数:4字节
half //16位浮点值
float //32位浮点值
double //64位浮点值
fp128 //128位浮点值
[<# elements> x ] //elements是一个恒定的整数值;elementtype可以是任何大小的类型。
alloca [24 x i8],algin 8 //24个8位整型值都是0的数组
[40 x i32] //40个32位整型值的数组。
[4 x i8] //4个8位整型值的数组。
[3 x [4 x i32]] //3x4的32位整型值数组。
[12 x [10 x float]] //12x10的单精度浮点值数组。
%T1 = type { } ; //正常结构体类型
%T2 = type <{ }> ; //封装结构体类型
//swift.refcounted结构体: 第一个元素为 swift.type类型的指针,第二位为64位整型值(8字节)
%swift.refcounted = type { %swift.type*,i64 }
{ i32, i32, i32 } //三组32位整形值
{ float, i32 (i32) * } //第一个元素为浮点型,第二个元素是一个指向函数的指针:该函数参数为32位整型值,返回32位整型值
<{ i8, i32 }> //被定义为一个5字节大小的封装结构体
*
i64* //指向 i64类型 的指针
[4 x i32]* //指向 4个i32类型的数组 的指针
i32 (i32*) * //指向 参数为i32、返回值为i32的函数 的指针
i32 addrspace(5)* //指向 在内存地址5中的i32类型 的指针
= getelementptr , * {, [inrange] }*
= getelementptr inbounds , * {, [inrange] }*
= getelementptr , , [inrange]
struct munger_struct {
int f1;
int f2;
};
void munge(struct munger_struct *p){
p[0].f1 = p[1].f1 + p[2].f2;
}
struct munger_struct array[3];
//int main(int argc, const char * argv[]) {
// munge(array); //将结构体数组传递给函数
// return 0;
//}
clang main.c -emit-llvm -S -c -o main.ll //LLVM IR 生成指令
clang StructIR/main.c -emit-llvm -S -c -o main.ll > ./main.ll && open main.ll //案例中生成并打开文件的指令
//1、定义了一个struct.munger_struct 的结构体 = 第一个参数为 i32,第二个参数也为 i32
%struct.munger_struct = type { i32, i32 }
//2、自定义的全局数组:3个 struct.munger_struct结构体类型的数组、并初始化
@array = common global [3 x %struct.munger_struct] zeroinitializer, align 16
define void @munge(%struct.munger_struct* %0) #0 {
//5、%2创建了一片内存空间、存放的是我们当前 struct.munger_struct结构体 的地址: 所以当前的%2是一个地址的地址(二级指针)
%2 = alloca %struct.munger_struct*, align 8
//由%struct.munger_struct** %2 可见 %2 二级指针
store %struct.munger_struct* %0, %struct.munger_struct** %2, align 8
// %3 = 当前数组的首地址
%3 = load %struct.munger_struct*, %struct.munger_struct** %2, align 8
//8、访问当前的p[1] : 当前index = 1,1 x 结构体大小(4字节)、访问我们数组当中的第二个元素p[1]
%4 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %3, i64 1
//9、访问数组中第二个结构体的第一个成员f1
%5 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %4, i32 0, i32 0
//14、 %6 = 访问 p[1].f1
%6 = load i32, i32* %5, align 4
//15、当前数组的首地址
%7 = load %struct.munger_struct*, %struct.munger_struct** %2, align 8
//10、访问当前的p[2]: 当前的 index = 2, 2 x 结构体大小(4字节),访问我们数组中的第三个元素p[2]
%8 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %7, i64 2
//11、访问数组中的第三个结构体的第二个成员f2
%9 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %8, i32 0, i32 1
//16、 %10 = 访问 p[2].f2
%10 = load i32, i32* %9, align 4
//17、 %11 = p[1].f1+p[2].f2
%11 = add nsw i32 %6, %10
//4、 %12 访问的是我们的 %2。 6、取出%2的首地址给%12;此时%12存放的是当前数组的首地址
%12 = load %struct.munger_struct*, %struct.munger_struct** %2, align 8
//3、 当前返回值类型位 %struct.munger_struct结构体类型、需要拿到数组的基地址,%struct.munger_struct* %12是当前索引结构体的地址、i64 0 当前数组的index;
%13 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %12, i64 0 //12、访问当前数组的第一个元素p[0]
//7、%13 是我们当前数组的第一个结构体元素;第一个i32 0 相当于结构体指针偏移0字节,也就是不偏移,第二个i32 0 表示第一个结构体成员
%14 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %13, i32 0, i32 0 //13、访问数组中第一个结构体的第一个成员f1
//18、 p[0].f1 = p[1].f1+p[2].f2
store i32 %11, i32* %14, align 4
ret void
}
int main(int argc, const char * argv[]) {
int array[4] = {1, 2, 3, 4};
int a = array[0];
return 0;
}
//其中 int a = array[0] 这句对应的LLVM代码应该是这样的:
%6 = alloca [4 x i32], align 16
%9 = getelementptr inbounds [4 x i32], [4 x i32]* %6, i64 0, i64 0
define i32 @main(i32 %0, i8** %1) #0 {
entry:
%2 = bitcast i8** %1 to i8*
%3 = call swiftcc { i8*, %swift.refcounted* } @"main.makeIncrementer() -> () -> Swift.Int"()
....
}
define hidden swiftcc { i8*, %swift.refcounted* } @"main.makeIncrementer() -> () -> Swift.Int"() #0 {
entry:
%runningTotal.debug = alloca %TSi*, align 8
%0 = bitcast %TSi** %runningTotal.debug to i8*
call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false)
//3、由swift_allocObject 分配出来的HeapObject对象 给到 %1
%1 = call noalias %swift.refcounted* @swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 24, i64 7) #1
//4、将 %1 转换为 <{ %swift.refcounted, [8 x i8] }>*指针类型、其中又包含了一个swift.refcounted结构体,并且分配了 8xi8也就是8字节内存空间、该空间存储的也就是我们的数值
%2 = bitcast %swift.refcounted* %1 to <{ %swift.refcounted, [8 x i8] }>* //9、<{ %swift.refcounted, [8 x i8] }>结构体为当前所创建出来的box
%3 = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, <{ %swift.refcounted, [8 x i8] }>* %2, i32 0, i32 1
//7、连续的8字节地址空间
%4 = bitcast [8 x i8]* %3 to %TSi*
store %TSi* %4, %TSi** %runningTotal.debug, align 8
//6、%TSi 为当前数组;数组的指针%TSi*; 第一个i32 0为TSi*类型首地址、第二个i32 0 取其中的第一个元素 i8
%._value = getelementptr inbounds %TSi, %TSi* %4, i32 0, i32 0
//5、将 i64 类型的数值 10 存储到 %._value中; 8、相当于将 10 存放到连续的8字节内存地址空间中
store i64 10, i64* %._value, align 8
%5 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #1
call void @swift_release(%swift.refcounted* %1) #1
//2、往 { i8*, %swift.refcounted* } 插入值;bitcast:unsafeBitCast按位转换、把当前的内嵌函数incrementr #1 () -> Swift.Int (i64)转换为 i8*
//也就是放入void * 8字节内存空间中、意味着当前的void *存的是我们内嵌函数的地址;%swift.refcounted* %1,1 又插入一个 %1;
//10、也就是将%1的HeapObject对象放到了结构体数据中
%6 = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (i64 (%swift.refcounted*)* @"partial apply forwarder for incrementr #1 () -> Swift.Int in main.makeIncrementer() -> () -> Swift.Int" to i8*), %swift.refcounted* undef }, %swift.refcounted* %1, 1
//1、函数调用后返回值的结果为一个结构体:第一个元素为 i8类型的指针(理解为 void*),第二个元素为 swift.refcounted 结构体类型的指针。并将 %6 该结构体类型返回
ret { i8*, %swift.refcounted* } %6
}
%swift.function = type { i8*, %swift.refcounted* }
%swift.refcounted = type { %swift.type*, i64 } // { (i64)* , i64} 该结构也就是我们的HeapObject对象
%swift.type = type { i64 }
%swift.full_type = type { i8**, %swift.type }
%swift.full_boxmetadata = type { void (%swift.refcounted*)*, i8**, %swift.type, i32, i8* }
%swift.bridge = type opaque
%Any = type { [24 x i8], %swift.type* }
%TSi = type <{ i64 }>
struct HeapObject {
var type:UnsafeRawPointer
var refCount:UInt64
}
struct FunctionData{
var ptr:UnsafeRawPointer
var captureValue:BoxType //BoxType代表范型T
}
struct Box {
var refCounted:HeapObject
var value:T
}
//这里必须包裹一层、不然当前的函数类型被当作泛型参数传递之后会被重新包裹一层;
struct VoidIntFunc {//包装一个f、使我们的返回值不受影响
var f: () -> Int //makeIncrementer() 的返回值
}
var makeInc = VoidIntFunc(f:makeIncrementer())
let ptrr = UnsafeMutablePointer>>.allocate(capacity: 1)
//Cannot convert value of type 'VoidIntFunc' to expected argument type 'FunctionData>'
ptrr.initialize(to: makeInc)
var makeInc = VoidIntFunc(f:makeIncrementer())
var ptr = UnsafeMutablePointer.allocate(capacity: 1)
ptr.initialize(to: makeInc)
let context = ptr.withMemoryRebound(to: FunctionData>.self, capacity: 1) {
$0.pointee
}
print(context.ptr) //0x00000001000056a0
print(context.captureValue.value) //7307466919713137513
print("end")//断点
$ nm ~/Library/Developer/Xcode/DerivedData/StructIR-alsccwttwgnzaobtshifjxvyffzg/Build/Products/Debug/ClosureInner | grep 00000001000056a0
00000001000056a0 t _$s12ClosureInner15makeIncrementerSiycyF10incrementrL_SiyFTA
$ nm ~/Library/Developer/Xcode/DerivedData/StructIR-alsccwttwgnzaobtshifjxvyffzg/Build/Products/Debug/ClosureInner | grep 00000001000056a0 | xcrun swift-demangle
00000001000056a0 t partial apply forwarder for incrementr #1 () -> Swift.Int in ClosureInner.makeIncrementer() -> () -> Swift.Int
func debugOutPrint(_ condition:Bool ,_ message:String) {
if condition {
print("\(message)")
}
}
debugOutPrint(ture, "Application Error Occured") //Application Error Occured
func debugOutPrint(_ condition:Bool ,_ message:String) {
if condition {
print("\(message)")
}
}
func doSomething() -> String {
print("test method")
return "Application Error Occured"
}
debugOutPrint(false, doSomething()) //test method
func debugOutPrint(_ condition:Bool ,_ message: () -> String) {
if condition {
print(message())
}
}
func doSomething() -> String {
print("doSomething method")
return "Application Error Occured"
}
debugOutPrint(false, doSomething) //
debugOutPrint(true, doSomething) //doSomething method \n Application Error Occured
debugOutPrint(true, doSomething())
debugOutPrint(true, "Application Error Occured")
{ //大概酱紫
"Application Error Occured String"
}
func debugOutPrint(_ condition:Bool ,_ message: @autoclosure () -> String) {
if condition {
print(message())
}
}
func doSomething() -> String {
print("doSomething method")
return "Application Error Occured"
}
debugOutPrint(true, doSomething())
debugOutPrint(true, "Application Error Occured String")
doSomething method
Application Error Occured
Application Error Occured String