Swift中如何存储泛型函数到变量?mutating方法存储疑问
Swift中函数作为一等公民的两个常见问题解答
一、泛型函数(如map)如何赋值给变量
直接写let fn = a.map时,编译器无法推断泛型参数T的具体类型——因为map的返回值类型由传入的转换闭包决定,此时没有提供闭包,类型自然无法确定。解决方法有两种:
1. 显式指定变量类型
给变量fn标注完整的函数类型,明确泛型参数T的具体实现:
let a = [1,2,3,4] // 明确T为String,fn的类型为((Int) -> String) -> [String] let fn: ((Int) -> String) -> [String] = a.map // 调用示例 let result = fn { String($0 * 2) } print(result) // ["2", "4", "6", "8"]
2. 用闭包包装并隐式推断类型
如果不想写冗长的类型标注,可通过闭包包装map调用,利用闭包的返回值隐式确定T:
let a = [1,2,3,4] let fn = { (transform: (Int) -> String) in a.map(transform) } // 调用方式一致 let result = fn { String($0) } print(result) // ["1", "2", "3", "4"]
二、mutating方法能否存入变量
不是完全不能,而是不能直接引用mutating方法作为函数值。因为mutating方法会修改实例本身,Swift不允许直接将这类方法从实例中提取为独立函数值(避免语义模糊:修改的是原实例还是副本?)。但可以通过闭包包装间接实现:
方法1:捕获固定实例调用mutating方法
import Collections var a = Deque<Int>([1,2,3,4]) // 必须用var,因为要修改实例 let fn = { (element: Int) in a.prepend(element) } // 调用闭包会直接修改原实例a fn(0) print(a) // Deque([0, 1, 2, 3, 4])
方法2:通过inout参数作用于任意实例
如果希望闭包能处理多个实例,可把实例作为inout参数传入:
import Collections let fn = { (deque: inout Deque<Int>, element: Int) in deque.prepend(element) } var a = Deque<Int>([1,2,3,4]) fn(&a, 0) print(a) // Deque([0, 1, 2, 3, 4]) var b = Deque<Int>([5,6]) fn(&b, 4) print(b) // Deque([4, 5, 6])
内容的提问来源于stack exchange,提问作者No No
相关产品推荐
相关产品推荐

