这里有Chris Lattner的完整解释,Swift的创始人。我将总结一下要点:
x += 1
更短的表达方式。for i = 0; i < n; i++ { ... }
,而Swift有更好的替代方案,如for i in 0..(C式for循环也即将淘汰)。
- 阅读和维护起来可能会比较棘手,例如,
x- ++x
或foo(++x, x++)
的值是什么?
- Chris Lattner不喜欢它。
对于那些感兴趣的人(并为了避免链接失效),Lattner用自己的话解释了原因:
这些运算符增加了学习Swift作为第一编程语言的负担,或者在您不从其他语言中已经知道这些运算符的情况下的任何情况。
它们的表达能力优势很小,x++
并没有比x += 1
短多少。
Swift已经偏离了C语言的模式,=、+=和其他类赋值操作返回Void(由于多种原因),这些运算符与该模式不一致。
Swift具有强大的功能,可以消除在其他语言中使用++i C风格for循环的许多常见原因,因此在编写良好的Swift代码中相对较少使用。这些特性包括for-in循环、范围、枚举、映射等等。
这些运算符实际使用其结果值的代码常常会让代码的读者/维护者感到困惑和微妙。它们鼓励编写“过于棘手”的代码,可能很巧妙,但难以理解。
虽然 Swift 有明确定义的计算顺序,但任何依赖此顺序的代码(如 foo(++a, a++))即使定义良好也不应该出现。
这些运算符适用于相对较少的类型:整数和浮点标量、类似迭代器的概念。它们不适用于复数、矩阵等。
最后,这些运算符不符合“如果我们没有它们,我们会在 Swift 3 中添加它们吗?”的标准。
++
,那么没有人会理智地看待 Swift 3.0 的设计,并认为将 ++
运算符作为其中的一个很好的补充。 - overactor++
和--
运算符。我不同意它们很棘手或难以管理的观点。一旦开发人员理解了这些运算符所做的事情(而我们谈论的是相当简单的东西),代码应该非常清晰。++
或--
运算符非常有用。varName++
返回一个值,因此可以在return
中使用,而varName += 1
则不行。prefix operator ++ {}
postfix operator ++ {}
prefix operator -- {}
postfix operator -- {}
// Increment
prefix func ++(inout x: Int) -> Int {
x += 1
return x
}
postfix func ++(inout x: Int) -> Int {
x += 1
return (x - 1)
}
prefix func ++(inout x: UInt) -> UInt {
x += 1
return x
}
postfix func ++(inout x: UInt) -> UInt {
x += 1
return (x - 1)
}
prefix func ++(inout x: Int8) -> Int8 {
x += 1
return x
}
postfix func ++(inout x: Int8) -> Int8 {
x += 1
return (x - 1)
}
prefix func ++(inout x: UInt8) -> UInt8 {
x += 1
return x
}
postfix func ++(inout x: UInt8) -> UInt8 {
x += 1
return (x - 1)
}
prefix func ++(inout x: Int16) -> Int16 {
x += 1
return x
}
postfix func ++(inout x: Int16) -> Int16 {
x += 1
return (x - 1)
}
prefix func ++(inout x: UInt16) -> UInt16 {
x += 1
return x
}
postfix func ++(inout x: UInt16) -> UInt16 {
x += 1
return (x - 1)
}
prefix func ++(inout x: Int32) -> Int32 {
x += 1
return x
}
postfix func ++(inout x: Int32) -> Int32 {
x += 1
return (x - 1)
}
prefix func ++(inout x: UInt32) -> UInt32 {
x += 1
return x
}
postfix func ++(inout x: UInt32) -> UInt32 {
x += 1
return (x - 1)
}
prefix func ++(inout x: Int64) -> Int64 {
x += 1
return x
}
postfix func ++(inout x: Int64) -> Int64 {
x += 1
return (x - 1)
}
prefix func ++(inout x: UInt64) -> UInt64 {
x += 1
return x
}
postfix func ++(inout x: UInt64) -> UInt64 {
x += 1
return (x - 1)
}
prefix func ++(inout x: Double) -> Double {
x += 1
return x
}
postfix func ++(inout x: Double) -> Double {
x += 1
return (x - 1)
}
prefix func ++(inout x: Float) -> Float {
x += 1
return x
}
postfix func ++(inout x: Float) -> Float {
x += 1
return (x - 1)
}
prefix func ++(inout x: Float80) -> Float80 {
x += 1
return x
}
postfix func ++(inout x: Float80) -> Float80 {
x += 1
return (x - 1)
}
prefix func ++<T : _Incrementable>(inout i: T) -> T {
i = i.successor()
return i
}
postfix func ++<T : _Incrementable>(inout i: T) -> T {
let y = i
i = i.successor()
return y
}
// Decrement
prefix func --(inout x: Int) -> Int {
x -= 1
return x
}
postfix func --(inout x: Int) -> Int {
x -= 1
return (x + 1)
}
prefix func --(inout x: UInt) -> UInt {
x -= 1
return x
}
postfix func --(inout x: UInt) -> UInt {
x -= 1
return (x + 1)
}
prefix func --(inout x: Int8) -> Int8 {
x -= 1
return x
}
postfix func --(inout x: Int8) -> Int8 {
x -= 1
return (x + 1)
}
prefix func --(inout x: UInt8) -> UInt8 {
x -= 1
return x
}
postfix func --(inout x: UInt8) -> UInt8 {
x -= 1
return (x + 1)
}
prefix func --(inout x: Int16) -> Int16 {
x -= 1
return x
}
postfix func --(inout x: Int16) -> Int16 {
x -= 1
return (x + 1)
}
prefix func --(inout x: UInt16) -> UInt16 {
x -= 1
return x
}
postfix func --(inout x: UInt16) -> UInt16 {
x -= 1
return (x + 1)
}
prefix func --(inout x: Int32) -> Int32 {
x -= 1
return x
}
postfix func --(inout x: Int32) -> Int32 {
x -= 1
return (x + 1)
}
prefix func --(inout x: UInt32) -> UInt32 {
x -= 1
return x
}
postfix func --(inout x: UInt32) -> UInt32 {
x -= 1
return (x + 1)
}
prefix func --(inout x: Int64) -> Int64 {
x -= 1
return x
}
postfix func --(inout x: Int64) -> Int64 {
x -= 1
return (x + 1)
}
prefix func --(inout x: UInt64) -> UInt64 {
x -= 1
return x
}
postfix func --(inout x: UInt64) -> UInt64 {
x -= 1
return (x + 1)
}
prefix func --(inout x: Double) -> Double {
x -= 1
return x
}
postfix func --(inout x: Double) -> Double {
x -= 1
return (x + 1)
}
prefix func --(inout x: Float) -> Float {
x -= 1
return x
}
postfix func --(inout x: Float) -> Float {
x -= 1
return (x + 1)
}
prefix func --(inout x: Float80) -> Float80 {
x -= 1
return x
}
postfix func --(inout x: Float80) -> Float80 {
x -= 1
return (x + 1)
}
prefix func --<T : BidirectionalIndexType>(inout i: T) -> T {
i = i.predecessor()
return i
}
postfix func --<T : BidirectionalIndexType>(inout i: T) -> T {
let y = i
i = i.predecessor()
return y
}
return (x - 1)
- 在我看来,保持它们返回(原始值的副本)的语义比返回 x + 1 - 1
更加清晰。 - AlnitakInt
类型,那么 (x + 1)
的结果将会溢出,这将中断执行,因此 result - 1
将不会被执行。其他数据类型如 Double
则表现不同,所以我需要进一步调查。 - 0101defer
来实现这一点。defer { x += 1 }; return x
- Tim Vermeulen苹果已经移除了 ++
,并使用另一种老传统方式简化了它。
你需要使用 +=
代替 ++
。
例子:
var x = 1
//Increment
x += 1 //Means x = x + 1
对于递减操作符--
,你需要写-=
例如:
var x = 1
//Decrement
x -= 1 //Means x = x - 1
对于 for
循环:
自增示例:
不要使用
for var index = 0; index < 3; index ++ {
print("index is \(index)")
}
您可以写:
//Example 1
for index in 0..<3 {
print("index is \(index)")
}
//Example 2
for index in 0..<someArray.count {
print("index is \(index)")
}
//Example 3
for index in 0...(someArray.count - 1) {
print("index is \(index)")
}
减量示例:
for var index = 3; index >= 0; --index {
print(index)
}
你可以写:
for index in 3.stride(to: 1, by: -1) {
print(index)
}
//prints 3, 2
for index in 3.stride(through: 1, by: -1) {
print(index)
}
//prints 3, 2, 1
for index in (0 ..< 3).reverse() {
print(index)
}
for index in (0 ... 3).reverse() {
print(index)
}
希望这有所帮助!+=
一直存在。 - Nicolas Miari++i
和 --i
代表对变量 i
的自增和自减操作,在表达式中使用时可以先进行自增或自减操作再参与后续的计算。 - Zigii Wong++
和--
操作符作为Int
和其他类型的扩展进行恢复。以下是一个示例:extension Int {
@discardableResult
static prefix func ++(x: inout Int) -> Int {
x += 1
return x
}
static postfix func ++(x: inout Int) -> Int {
defer {x += 1}
return x
}
@discardableResult
static prefix func --(x: inout Int) -> Int {
x -= 1
return x
}
static postfix func --(x: inout Int) -> Int {
defer {x -= 1}
return x
}
}
对于其他类型,比如 UIInt
, Int8
, Float
, Double
等,它们的工作方式也是相同的。
你可以将这些扩展粘贴到根目录下的单个文件中,它们将可用于所有其他文件中。如果在 playground 中检查,它完美地工作。
...for i in 0.stride(to: 10, by: 2)...
或者 ...for i in (1...10).reverse()...
这样的写法简洁明了吗? - mad_manny这是目前为止发布的代码的一个通用版本。我和其他人一样都认为,不应该在Swift中使用这些方法,这是最佳实践。我同意,这可能会让未来阅读你的代码的人感到困惑。
prefix operator ++
prefix operator --
prefix func ++<T: Numeric> (_ val: inout T) -> T {
val += 1
return val
}
prefix func --<T: Numeric> (_ val: inout T) -> T {
val -= 1
return val
}
postfix operator ++
postfix operator --
postfix func ++<T: Numeric> (_ val: inout T) -> T {
defer { val += 1 }
return val
}
postfix func --<T: Numeric> (_ val: inout T) -> T {
defer { val -= 1 }
return val
}
@discardableResult
以消除有关未使用返回值的警告;否则正是我要找的。 - Devin Lane从文档中得知:
Swift的递增/递减运算符非常早就加入了Swift的开发,是从C语言中继承过来的。这些运算符在加入时并没有经过多少考虑,并且自那时以来也没有得到多少关注。本文提供了一个新的视角来看待它们,并最终建议我们完全删除它们,因为它们令人困惑,而且没有起到作用。
var value : Int = 1
func theOldElegantWay() -> Int{
return value++
}
func theNewFashionWay() -> Int{
let temp = value
value += 1
return temp
}
这肯定是一个不利因素,对吧?
var x = y
++x
人类读取++x
,但解析器可能会将其读取为y++
。