自定义运算符错误 - 无法传递不可变值



我做错了什么?我试图了解自定义运算符如何在 swift 中工作。

enum MyEnum: String {
case String = "String"
static func << (lhs: inout String?, rhs: MyEnum) {
lhs = rhs.rawValue
}
}
class MyClass {
var value: String?
}
let myClass: MyClass? = MyClass()
myClass!.value << MyEnum.String
myClass!.value // "String"
myClass?.value << MyEnum.String // error: cannot pass immutable value of type 'String?' as inout argument

我怎样才能让它工作?

这与你的自定义运算符无关,这很好(虽然,为什么不直接使用赋值?

inout值必须是可变的。表达式的类型myClass?.value是不可变的Optional<String>。这是因为可选链接,不像myClass!.value强制解开包装myClass然后应用成员访问权限。

问题是<<在语义上是一个非变异运算符。因此,它的precedencegroup没有定义assignment属性设置为true,这意味着运算符不遵循与可选链接相同的分组规则。

因此,<<的重载不能与可选的链接结合使用(但即使可以;你不应该用变异实现重载非变异运算符,那只是令人困惑)。

如果要重载assignment设置为true的运算符,您的代码可以正常工作。例如,它可以与<<=一起使用 - 尽管实际上并没有这样做,因为<<=已经有一个既定的含义(就地左位移),你不符合。

如果你真的需要这里的操作员;我建议你定义你自己的:

precedencegroup CustomAssignment {
assignment: true // Allow the operator to be used with optional chaining.
}
infix operator <~ : CustomAssignment
enum MyEnum : String {
case string = "String"
static func <~ (lhs: inout String?, rhs: MyEnum) {
lhs = rhs.rawValue
}
}
class MyClass {
var value: String?
}
let myClass: MyClass? = MyClass()
myClass?.value <~ MyEnum.string
print(myClass?.value as Any) // Optional("String")

不过就我个人而言,我看不到这样的运营商的价值超过
myClass?.value = MyEnum.string.rawValue.后者更清晰,只有几个额外的字符。

最新更新