Я использую AtomicBox
от Matt Галлахера CwlUtils в небольшой обратный отсчет:Мутирование закрытия не компилируется, если оно сложнее, чем одно утверждение - как исправить?
class Countdown {
private let counter: AtomicBox<Int>
init(from start: Int) {
self.counter = AtomicBox(start)
}
func countDown() {
self.counter.mutate { $0 -= 1 }
}
}
Это работает просто отлично. Теперь предположим, что я хочу бросить ошибку, если счетчик уже достиг нуля:
func countDown() throws {
self.counter.mutate {
guard $0 > 0 else {
throw MyError.alreadyZero
}
$0 -= 1
}
}
Теперь swift build
жалуется: (. Weird сообщение об ошибке, кстати, они обычно приходят лучше)
<unknown>:0: error: parameters may not have the 'var' specifier
<unknown>:0: error: build had 1 command failures
error: exit(1): /Applications/Xcode8.2/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-build-tool -f /Users/dhtp/Documents/CwlUtils/.build/debug.yaml
Что здесь происходит? Обе версии мутируют внутреннее значение counter
(что и передается параметру mutate
) точно так же. Почему один законный, а другой нет?
Как я могу объявить закрытие так, чтобы оно скомпилировалось (и делает то, что я хочу)?
Я пробовал { (inout value) in ... }
, но это дает ту же ошибку.
Мое предположение заключается в том, что компилятор каким-то образом видит его в качестве модификации передаваемой функции 'mutate'. вид фанки. – PeejWeej
[Готово] (https://bugs.swift.org/browse/SR-3973), спасибо! – Raphael
@PEEJWEEJ Функция не бросания рассматривается как специализация функции бросания с теми же параметрами, то есть '(inout Int) -> Void' является подтипом' (inout Int) throws -> Void'. Таким образом, вы можете использовать функцию throw throw, где параметр объявляется как металирование, но вы не можете использовать функцию throwing, где параметр не объявляется как металирование. – JeremyP