Swift - 在闭包中计算不可变对象效率低吗?

Swift - is it inefficient to calculate an immutable within a closure?

我喜欢案例 2,因为它将相关代码放在一个地方,但是如果我这样做,每次计算闭包时常量都会重新计算吗?

let numCols = 99

// case 1
let spacing = (width - margin.left - margin.right) / (numCols - 1)
let xCoord = { (Int: col) -> Float in margin.left + col * spacing }

// case 2
let xCoord = { (Int: col) -> Float in
    let spacing = (width - margin.left - margin.right) / (numCols - 1)
    return margin.left + col * spacing
}

简短的回答是肯定的,在闭包中计算不可变是低效的。

原因如下。假设您有这样的代码:

let numCols = 99.0
let width = 800.0
let marginLeft = 15.0
let marginRight = 20.0

// case 1
let spacing: Double = (width - marginLeft - marginRight) / (numCols - 1)
let xCoord1 = { (col: Double) -> Double in
    return marginLeft + col * spacing
}

// case 2
let xCoord2 = { (col: Double) -> Double in
    let spacing: Double = (width - marginLeft - marginRight) / (numCols - 1)
    return marginLeft + col * spacing
}

这些是您示例中的情况 1 和情况 2,稍作修改以在 Playground 中编译。

让我们做一个简单的 for 循环来测量这些函数每个执行 2500 次:

let startTime = CACurrentMediaTime()
for var i in 0...2500
{
    xCoord1(10)
}
let totalTime = CACurrentMediaTime() - startTime
print("time: - \(totalTime) sec")

案例 1 在我的机器上执行时间为 0.99 秒(如果您的硬件特性较低或较高,可能会有所不同)。

现在,让我们看看如果对案例 2 执行相同操作会得到什么:

let startTime2 = CACurrentMediaTime()
for var i in 0...2500
{
    xCoord2(10)
}
let totalTime2 = CACurrentMediaTime() - startTime2
print("time: - \(totalTime2) sec")

案例 2 在我的机器上执行时间为 1.49 秒,这意味着它的效率低于案例 1。

因此,如果您的宽度、边距和列数不变,最好计算一次间距并将其存储在常量中。 但是,如果您不必多次重复此计算而只需要一次,您仍然可以将其保留在闭包中以提高可读性。 在您的环境中使用衡量性能的代码,看看您是否失去了性能,并据此做出决定。