问题描述
给定以下函数:
func greatestCommonDenominator(first: Int, second: Int) -> Int {
return second == 0 ? first : greatestCommonDenominator(second, first % second)
}
还有一个包含以下内容的结构:
And a struct with the following stuff in it:
struct Fraction {
var numerator: Int
var denominator: Int
func reduce() {
let gcd = greatestCommonDenominator(numerator,denominator)
self.numerator /= gcd
self.denominator /= gcd
}
// stuff
}
我收到以下错误:
error: 'Int' is not convertible to '@lvalue Float'
self.numerator /= gcd
^
error: 'Int' is not convertible to '@lvalue Float'
self.denominator /= gcd
^
'@lvalue Float'
?!?!?什么?我这里的任何地方都没有 Float.并且文档似乎表明 /=
应该返回一个 Int
,因为我正在划分两个 Int
s.我该如何解决这个问题?
'@lvalue Float'
?!?!? What? I don't have a Float anywhere in here. And the documentation seems to suggest that the /=
should return an Int
as I'm dividing two Int
s. How do I fix this?
附录:我在结构中遇到了这个问题,但是这个问题似乎可以在任何地方重现.
ADDENDUM: I came across this problem working within a struct, however the problem seems reproducible anywhere.
let a = 10
a /= 5
这会产生同样的问题.即使我们明确输入 a
作为 Int
:
This will produce the same problem. Even if we explicitly type a
as an Int
:
let a: Int = 10
a /= 5
同样的问题仍然存在.Swift 似乎认为两个 Int 之间的 /=
运算符的结果是 Float.
The same problem remains. Swift seems to think the result of the /=
operator between two Ints is a Float.
附录的问题实际上并不是 a/= 5
不起作用.确实如此!
The problem with the addendum isn't actually that a /= 5
doesn't work. It does actually!
var a: Int = 4
var b: Int = 3
a /= b
现在a
是3.附录中的问题与struct类似.在附录中,a
被声明为 let
而不是 var
,因此它是不可赋值的.
Now a
is 3. The problem in the addendum was similar to the struct. In the addendum, a
was declared as a let
rather than a var
, and as such it is unassignable.
推荐答案
如果您首先将函数更改为以下内容,您会收到更有用的错误消息:
If you start by changing the function to the following you get a more helpful error message:
func reduce() {
let gcd = greatestCommonDenominator(numerator,denominator)
self.numerator = self.numerator / gcd
self.denominator = self.denominator / gcd
}
现在错误变成:
error: cannot assign to 'numerator' in 'self'
self.numerator = self.numerator / gcd
~~~~~~~~~~~~~~ ^
对于我们这些来自 Objective-C(或不是 RTFM)的人来说,可能不是很明显的是,默认情况下,不允许结构体中的函数更改结构体的属性.您可以通过将函数显式声明为变异函数来解决此问题:
What may not be immediately obvious to those of us who are coming from Objective-C (or didn't RTFM) is that by default, functions in structs are not allowed to change the properties of a struct. You can get around this by explicitly declaring the function as a mutating function:
mutating func reduce() {
let gcd = greatestCommonDenominator(numerator,denominator)
self.numerator /= gcd
self.denominator /= gcd
}
变异词解决了这两个错误.
The mutating word solves both errors.
在 /=
的情况下,该错误非常神秘且无益.我将提交错误报告并鼓励其他人也这样做.
In the case of /=
, the error is quite cryptic and unhelpful. I'll be filing a bug report and encourage others to do so as well.
这里真正的问题与结构或复合赋值运算符无关.
The real problem here has nothing to do with structs or compound assignment operators.
这里的问题与我们试图分配给一个不可分配的右值有关.在结构体的情况下,右值是不可赋值的,因为函数没有被声明为可变的.对于 let
变量,它是不可赋值的,因为 let
就是这样工作的.然而,错误消息仍然具有误导性和混淆性.错误不是暗示可能存在类型不匹配,而是告诉我们右值不可分配,就像我们在 Objective-C 中尝试分配 const
一样.
The problem here has to do with the fact that we're trying to assign to an rvalue that's unassignable. In the case of the struct, the rvalue was unassignable because the function was not declared as mutating. In the case of the let
variable, it was unassignable because that's how let
works. The error message is still misleading and confusing however. Rather than suggesting that there might be a type mismatch, the error should inform us that the rvalue is unassignable, just as it would if we tried to assign a const
in Objective-C.
这篇关于错误:“Int"不能转换为“@lvalue Float"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!