Fat*_*tie 5 static swift computed-properties
这是一个简单的Swift函数
fileprivate func test()->String{
let c = Array("abc".characters)
let k = UInt32(c.count)
let r = Int(arc4random_uniform(k))
return String(c[r])
}
Run Code Online (Sandbox Code Playgroud)
(我选择这个例子是因为很明显,你可能会调用数十亿次来生成某种输出;所以你可能会担心设置两个常量的性能.)
请注意,它必须进行一些计算才能获得c,并且确实k需要使用它c.
我的问题很简单:每次调用此函数
test()
test()
test()
Run Code Online (Sandbox Code Playgroud)
实际上它是在计算k,和/或c 每次调用它,或者它们实际上只计算一次?
(如果"只有一次",那么作为一个好奇心:它是第一次调用函数时这样做?或者编译器可能会在启动时单独完成它?或者就此而言它是否知道它可以在编译期间计算它们?)
我经常使用全局计算属性,就像这样
let basicDF : DateFormatter = {
print("this will only be done once per launch of the app")
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
Run Code Online (Sandbox Code Playgroud)
(也许有fileprivate)如果上面问题的答案是"no,c并且每次调用test时计算'k',那么在这种情况下如何在函数中放置一种静态计算属性?
不,在您的特定情况下,编译器当前不会优化c和/或k只计算一次的常量表达式(这可以通过检查 IR看出)检查优化构建中的看出)\xe2\x80\x93 尽管这就是全部可能会随着该语言的未来版本而变化。
但值得注意的是,它目前可以对更简单的表达式执行此操作,例如:
\n\nfunc foo() -> Int {\n return 2 + 4\n}\nRun Code Online (Sandbox Code Playgroud)\n\n编译器可以在编译时评估加法,因此该函数只是执行return 6(然后可以内联)。但当然,如果您实际上已将给定函数确定为性能瓶颈,那么您首先应该担心此类优化。
在函数中获取静态常量的一个好技巧是定义一个无大小写的enum在函数中获取静态常量的一个好技巧是在函数作用域中
func test() -> String {\n\n enum Constants {\n static let c = Array("abc".characters)\n static let k = UInt32(c.count)\n }\n\n let r = Int(arc4random_uniform(Constants.k))\n return String(Constants.c[r])\n}\nRun Code Online (Sandbox Code Playgroud)\n\nc现在和的初始化表达式k只会被计算一次,并且这将在第一次使用它们时(即第一次调用函数时)完成。
当然,正如您所展示的,您可以使用立即计算的闭包以获得多行初始化表达式:
\n\nenum Constants {\n static let c: [Character] = {\n // ...\n return Array("abc".characters)\n }()\n // ...\n}\nRun Code Online (Sandbox Code Playgroud)\n