就地改变值类型关联值
Mutate a value-type associated value in-place
是否可以在 Swift 中改变枚举关联值,这是一种值类型?如果是,如何?
struct S {
var a = 1
}
enum E {
case s(S)
}
var e = E.s(S())
// the goal is to make e hold s with a = 2
// overwriting e is not allowed
if case var .s(s) = e {
// s is a copy at this point
// I want to mutate e in-place
s.a = 2
}
注意: 这似乎是可能的,至少对于 Optional
枚举 s?.a = 2
突变 Optional<S>
.
用例:
我正在围绕 Codable
编写一个小型包装器,以便轻松地在字典和对象之间映射值。我有一个 MappingContext
,它是 encode
或 decode
。鉴于 KeyedEncodingContainer
在编码时有一个变异函数,我希望这个包装器的用户避免重新分配值,而直接改变关联的值。
我打开了 swift stdlib 代码,该函数甚至没有改变结构,但被标记为正在改变。不知道为什么,但我现在可以毫无问题地获得副本,但重新分配也是一个可以接受的解决方案,只是想确保我没有遗漏任何明显的东西。
typealias EncodeContainer = KeyedEncodingContainer<JsonCodingKey>
typealias DecodeContainer = KeyedDecodingContainer<JsonCodingKey>
public enum CodingMode {
case encode(EncodeContainer)
case decode(DecodeContainer)
}
不可能在不覆盖枚举本身的情况下更改枚举关联值;如果相反 S
被声明为 class
,这是一个非常微不足道的任务。
无论如何,我做了一些我在这里报告的实验:
1) 基于withUnsafeMutablePointer:
var e = E.s(S(a: 1))
withUnsafeMutablePointer(to: &e, {
[=10=].pointee = E.s(S(a: 2))
})
print(e)
2) 声明一个变异 func
用于隐式覆盖枚举
struct S {
var a = 1
}
enum E {
case s(S)
mutating func setS(val:S) { self = E.s(val) }
}
var e = E.s(S(a: 1))
e.setS(val: S(a: 2))
print(2)
3) 如果 S
是 class
:
class S:CustomDebugStringConvertible {
var a = 1
var debugDescription: String { return "\(a)" }
}
enum E {
case s(S)
}
let e = E.s(S())
if case let .s(s) = e {
s.a = 2
}
print(e)
是否可以在 Swift 中改变枚举关联值,这是一种值类型?如果是,如何?
struct S {
var a = 1
}
enum E {
case s(S)
}
var e = E.s(S())
// the goal is to make e hold s with a = 2
// overwriting e is not allowed
if case var .s(s) = e {
// s is a copy at this point
// I want to mutate e in-place
s.a = 2
}
注意: 这似乎是可能的,至少对于 Optional
枚举 s?.a = 2
突变 Optional<S>
.
用例:
我正在围绕 Codable
编写一个小型包装器,以便轻松地在字典和对象之间映射值。我有一个 MappingContext
,它是 encode
或 decode
。鉴于 KeyedEncodingContainer
在编码时有一个变异函数,我希望这个包装器的用户避免重新分配值,而直接改变关联的值。
我打开了 swift stdlib 代码,该函数甚至没有改变结构,但被标记为正在改变。不知道为什么,但我现在可以毫无问题地获得副本,但重新分配也是一个可以接受的解决方案,只是想确保我没有遗漏任何明显的东西。
typealias EncodeContainer = KeyedEncodingContainer<JsonCodingKey>
typealias DecodeContainer = KeyedDecodingContainer<JsonCodingKey>
public enum CodingMode {
case encode(EncodeContainer)
case decode(DecodeContainer)
}
不可能在不覆盖枚举本身的情况下更改枚举关联值;如果相反 S
被声明为 class
,这是一个非常微不足道的任务。
无论如何,我做了一些我在这里报告的实验:
1) 基于withUnsafeMutablePointer:
var e = E.s(S(a: 1))
withUnsafeMutablePointer(to: &e, {
[=10=].pointee = E.s(S(a: 2))
})
print(e)
2) 声明一个变异 func
用于隐式覆盖枚举
struct S {
var a = 1
}
enum E {
case s(S)
mutating func setS(val:S) { self = E.s(val) }
}
var e = E.s(S(a: 1))
e.setS(val: S(a: 2))
print(2)
3) 如果 S
是 class
:
class S:CustomDebugStringConvertible {
var a = 1
var debugDescription: String { return "\(a)" }
}
enum E {
case s(S)
}
let e = E.s(S())
if case let .s(s) = e {
s.a = 2
}
print(e)