给出以下功能:
func greatestCommonDenominator(first: Int, second: Int) -> Int {
return second == 0 ? first : greatestCommonDenominator(second, first % second)
}
结构中包含以下内容:
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
分开。我该如何解决这个问题?
ADDENDUM:我在一个结构中遇到了这个问题,但问题似乎在任何地方都可以重现。
let a = 10
a /= 5
这会产生同样的问题。即使我们明确地将a
键入为Int
:
let a: Int = 10
a /= 5
同样的问题依然存在。 Swift似乎认为两个Ints之间的/=
运算符的结果是Float。
编辑:附录的问题实际上并非a /= 5
无法正常工作。它实际上确实!
var a: Int = 4
var b: Int = 3
a /= b
现在a
是3.附录中的问题类似于结构。在附录中,a
被声明为let
而不是var
,因此它是无法分配的。
答案 0 :(得分:4)
如果您首先将功能更改为以下内容,则会收到更有用的错误消息:
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)的人来说,显而易见的是,默认情况下,结构中的函数不允许更改结构的属性。你可以通过明确地将函数声明为变异函数来解决这个问题:
mutating func reduce() {
let gcd = greatestCommonDenominator(numerator,denominator)
self.numerator /= gcd
self.denominator /= gcd
}
变异词解决了两个错误。
在/=
的情况下,错误非常神秘且无益。我将提交错误报告,并鼓励其他人也这样做。
编辑:此处的实际问题与结构或复合赋值运算符无关。
这里的问题与我们试图分配给无法分配的右值这一事实有关。在结构的情况下,rvalue是不可分配的,因为该函数未被声明为变异。对于let
变量,它是无法分配的,因为let
的工作原理。但错误信息仍然具有误导性和混乱性。错误应该通知我们rvalue是无法分配的,就像我们尝试在Objective-C中分配const
一样,而不是建议可能存在类型不匹配。