我正在查看 Xcode 7.3 笔记,我注意到了这个问题。
++ 和 -- 运算符已被弃用
有人可以解释为什么它被弃用吗?我是对的,现在在新版本的 Xcode 中你将使用它来代替++
这个x += 1
;
例子:
for var index = 0; index < 3; index += 1 {
print("index is \(index)")
}
Swift 的创造者 Chris Lattner在这里给出了完整的解释。我总结一下几点:
x += 1
for i = 0; i < n; i++ { ... }
,Swift 有更好的替代品,比如for i in 0..<n { ... }
(C 风格的 for 循环也将退出)x - ++x
什么foo(++x, x++)
?对于那些感兴趣的人(并且为了避免链接失效),Lattner 用他自己的话来说的原因是:
这些运算符增加了学习 Swift 作为第一门编程语言的负担——或者任何其他你还不知道这些运算符来自不同语言的情况。
它们的表达优势很小——x++ 并不比 x += 1 短很多。
Swift 已经偏离了 C,因为 =、+= 和其他类似赋值的操作返回 Void(出于多种原因)。这些运算符与该模型不一致。
Swift 具有强大的功能,可以消除您在其他语言的 C 风格 for 循环中使用 ++i 的许多常见原因,因此这些在编写良好的 Swift 代码中相对较少使用。这些功能包括 for-in 循环、范围、枚举、映射等。
实际使用这些运算符的结果值的代码对于代码的读者/维护者来说通常是令人困惑和微妙的。他们鼓励“过于棘手”的代码,这些代码可能很可爱,但很难理解。
虽然 Swift 有明确定义的评估顺序,但任何依赖于它的代码(如 foo(++a, a++))即使定义明确也是不可取的。
这些运算符适用于相对较少的类型:整数和浮点标量,以及类似迭代器的概念。它们不适用于复数、矩阵等。
最后,这些都没有达到“如果我们还没有这些,我们会将它们添加到 Swift 3 中吗?”的标准。
我意识到这个评论并没有回答这个问题,但是可能有人在寻找如何让这些操作员继续工作的解决方案,这样的解决方案可以在底部找到。
我个人比较喜欢++
和--
运营商。我不同意他们棘手或难以管理的观点。一旦开发人员了解了这些运算符的作用(我们谈论的是非常简单的东西),代码应该非常清晰。
在解释为什么不推荐使用运算符时提到它们的主要用途是 C 风格的 for 循环。我不了解其他人,但我个人根本不使用 C 风格的循环,还有很多其他地方或情况下++
or--
运算符很有用。
我还想提一下,它varName++
返回一个值,因此它可以在return
while中使用,但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
}
Apple 已经删除++
了它,并使用另一种旧的传统方式使其变得更简单。
而不是++
,您需要编写+=
.
例子:
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)
}
希望这可以帮助!
对于 Swift 4,您可以将++
and--
运算符恢复为Int
and 其他类型的扩展。这是一个例子:
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
等。
您可以将这些扩展粘贴到根目录中的单个文件中,并且它们可以在您那里的所有其他文件中使用。如果您在操场上查看它,它会完美运行。
Chris Lattner 与 ++ 和 -- 开战。他写道,“实际使用这些运算符的结果值的代码对于代码的读者/维护者来说往往是令人困惑和微妙的。他们鼓励“过于棘手”的代码,这些代码可能很可爱,但难以理解……虽然 Swift 有明确定义的评估顺序,但任何依赖它的代码(如 foo(++a, a++))都是不可取的,即使它是明确定义的……这些没有达到“如果我们还没有这些,我们会将它们添加到 Swift 3 中吗?”的度量标准</p>
Apple 希望保持 swift 是一种干净、清晰、不混淆且直截了当的语言。所以他们弃用了 ++ 和 -- 关键字。
这是迄今为止发布的一些代码的通用版本。我会表达和其他人一样的担忧:最好不要在 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
}
这也可以写为 Numeric 类型的扩展。
从文档:
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++
.
由于您在 Swift 中从未真正使用过指针,因此在我看来删除++
and运算符是有意义的。--
但是,如果您不能没有,您可以将这些Swift 5+运算符声明添加到您的项目中:
@discardableResult
public prefix func ++<T: Numeric>(i: inout T) -> T {
i += 1
return i
}
@discardableResult
public postfix func ++<T: Numeric>(i: inout T) -> T {
defer { i += 1 }
return i
}
@discardableResult
public prefix func --<T: Numeric>(i: inout T) -> T {
i -= 1
return i
}
@discardableResult
public postfix func --<T: Numeric>(i: inout T) -> T {
defer { i -= 1 }
return i
}
在 Swift 4.1 中可以这样实现:
prefix operator ++
postfix operator ++
extension Int{
static prefix func ++(x: inout Int)->Int{
x += 1
return x
}
static postfix func ++(x: inout Int)->Int{
x += 1
return x-1
}
}
//example:
var t = 5
var s = t++
print("\(t) \(s)")
请注意,尽管此解决方案与本文中的先前解决方案相似,但它们在 Swift 4.1 中不再有效,而本示例则有效。另请注意,上面提到 += 是 ++ 的替代品的任何人都没有完全理解运算符,因为 ++ 与赋值相结合实际上是两个操作,因此是一种快捷方式。在我的例子中:var s = t++
做两件事:将 t 的值分配给 s,然后增加 t。如果 ++ 出现在前面,则相同的两个操作以相反的顺序完成。在我看来,Apple 关于为什么要删除此运算符的推理(在之前的答案中提到)不仅是错误的推理,而且我认为这是一个谎言,真正的原因是他们无法让编译器处理它。在以前的版本中给他们带来了麻烦,所以他们放弃了。“太复杂而无法理解运算符,因此被删除”的逻辑显然是一个谎言,因为 Swift 包含的运算符要复杂得多,用处也少得多,这些运算符没有被删除。此外,绝大多数编程语言都有它。JavaScript、C、C#、Java、C++ 等等。程序员乐于使用它。对谁来说太难理解这个运算符,
Swift 背后的策略很简单:Apple 认为程序员是愚蠢的,因此应该受到相应的对待。
事实是,2014 年 9 月推出的 Swift 现在应该在其他地方。其他语言发展得更快。
我可以列出该语言中的许多主要错误,从严重的错误:例如按值而不是按引用粘贴的数组,到令人讨厌的错误:可变参数函数不能接受数组,这是其背后的全部思想。我不认为 Apple 的员工甚至被允许查看 Java 等其他语言,所以他们甚至不知道 Apple 落后了很多年。苹果本可以采用 Java 作为一种语言,但如今,挑战不是技术,而是自我。如果他们打开 IntelliJ 来编写一些 Java,他们肯定会关闭他们的业务,因为他们明白,在这一点上,他们无法也永远不会赶上。