“++”和“--”运算符已被弃用 Xcode 7.3

Posted

技术标签:

【中文标题】“++”和“--”运算符已被弃用 Xcode 7.3【英文标题】:The "++" and "--" operators have been deprecated Xcode 7.3 【发布时间】:2016-05-11 13:12:40 【问题描述】:

我正在查看 Xcode 7.3 注释,我注意到了这个问题。

++ 和 -- 运算符已被弃用

有人能解释一下为什么不推荐使用它吗?我对吗,现在在新版本的 Xcode 中你要使用 ++ 而不是 x += 1;

例子:

for var index = 0; index < 3; index += 1 
    print("index is \(index)")

【问题讨论】:

我认为这个问题如果超出了***的范围主要是因为所有被接受的关于快速进化的提案都可以在Github中找到,你可以阅读更多关于这个提案的原因github.com/apple/swift-evolution/blob/master/proposals/…跨度> 我正在认真考虑回到Objective-C。尝试跟上 Swift 的所有变化是不值得的。 @OlegGordiichuk 这也是 C 风格的 for 循环也将被删除的东西,请参阅此 github.com/Vkt0r/swift-evolution/blob/master/proposals/…,因此您不需要使用更多 ++-- 运算符 我的口味有太多重大变化。我完全赞成改进,但我真的不想在每次 Xcode 点发布时都花时间重写我的代码库的大部分内容。 @Fogmeister 我不确定我怎么能更清楚。我更喜欢使用 Swift,但我觉得它不够稳定。过去我曾与其他语言进行过广泛的合作,并且从未在如此短的时间内遇到如此多的重大变化。我觉得 Apple 希望我们所有人都采用 Swift,但他们让这变得比应有的困难。 【参考方案1】:

来自 Swift 的创造者 Chris Lattner 的full explanation here。我总结一下几点:

    这是您在学习 Swift 时必须学习的另一个功能 不比x += 1短多少 Swift 不是 C。不应该仅仅为了取悦 C 程序员而把它们带过来 它的主要用途是 C 风格的 for 循环:for i = 0; i &lt; n; i++ ... ,Swift 有更好的替代品,比如 for i in 0..&lt;n ... (C 风格的 for 循环是 going out as well) 可能难以阅读和维护,例如,x - ++xfoo(++x, x++) 的值是多少? Chris Lattner 不喜欢它。

对于那些感兴趣的人(并且为了避免链接失效),Lattner 用他自己的话来说的原因是:

    这些运算符增加了将 Swift 作为第一种编程语言学习的负担 - 或者您还不知道这些运算符来自其他语言的任何其他情况。

    它们的表达优势很小 - x++ 并不比 x += 1 短很多。

    Swift 已经偏离了 C,因为 =、+= 和其他类似赋值的操作返回 Void(出于多种原因)。这些运算符与该模型不一致。

    Swift 具有强大的功能,可以消除您在其他语言的 C 风格 for 循环中使用 ++i 的许多常见原因,因此这些在编写良好的 Swift 代码中相对较少使用。这些功能包括 for-in 循环、范围、枚举、映射等。

    实际使用这些运算符的结果值的代码通常会使代码的读者/维护者感到困惑和微妙。他们鼓励“过于棘手”的代码,这些代码可能很可爱,但很难理解。

    虽然 Swift 有明确定义的求值顺序,但任何依赖于它的代码(如 foo(++a, a++))即使定义明确也是不可取的。

    这些运算符适用于相对较少的类型:整数和浮点标量,以及类似迭代器的概念。它们不适用于复数、矩阵等。

最后,这些都没有达到“如果我们还没有这些,我们会将它们添加到 Swift 3 中吗?”这一指标。

【讨论】:

我的意思是,真正的答案是 6 号。没关系,我们(前 C、Java、... 程序员)足够灵活 :-)。一般来说,对于现实世界来说,变异、交叉和选择就足够了。我、你和克里斯也是,我们都是这三个运营商的结果…… 第 5 点:那些在 C 中总是依赖于实现的,没有任何人做过。只需定义行为,我们就会习惯它。总比无缘无故地返回并更改完美的旧代码要好。 我喜欢第 3 点。你不能永远被传统的契约束缚。我喜欢 C 但你正在创建一种新的编程语言;从你需要的干净的石板开始是有意义的。 这是因为苹果喜欢强迫你像他们一样思考。我认为它非常好,可以在需要增加或减少变量的任何地方使用。这不是你“必须学习”的东西,没有它你会做得很好。而#5 只是写得很糟糕的代码,我从未见过这样的代码。所以#6是。贬低它足以让我挠头并进行谷歌搜索,所以感谢克里斯浪费我的时间。 @csga5000 这是一个相当弱的论点,因为如果你真的想的话,你可以自己定义操作符。这与苹果希望人们像他们一样思考无关。它根本不适合这种语言。如果 ++ 不存在于 C 风格的语言中,那么任何头脑正常的人都不会看到 Swift 3.0 的设计并认为 ++ 运算符会是一个很好的补充。【参考方案2】:

我意识到这个评论并没有回答这个问题,但是可能有人在寻找如何让这些操作员继续工作的解决方案,这样的解决方案可以在底部找到。 ?

我个人更喜欢++-- 运算符。我不同意他们棘手或难以管理的观点。一旦开发人员了解了这些运算符的作用(我们谈论的是非常简单的东西),代码应该非常清晰。

在解释为什么不推荐使用运算符时提到它们的主要用途是 C 风格的 for 循环。我不知道其他人,但我个人根本不使用 C 风格的循环,还有很多其他地方或情况 ++-- 运算符有用。

我还想提一下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 我也不喜欢它,但我不知道有任何其他(更好、更清洁)的方法。我不完全理解你的第二点。 我明白了,我不想仅仅为了创建另一个变量(或者在这种情况下是常量)而这样做。如果我们只讨论Int,那么(x + 1) 的结果将被溢出,这将中断执行,因此result - 1 甚至不会被运行。例如,Double 等其他数据类型的行为方式不同,因此我需要对此进行调查。 您也可以为此使用deferdefer x += 1 ; return x 为什么不用泛型,用几行代码写出来?【参考方案3】:

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)

希望这会有所帮助!

【讨论】:

他们没有更换任何东西; += 一直都在。 @NicolasMiari 是的,只是用更好的格式编辑 @NicolasMiari 你现在可以检查一下吗? ++i--i 怎么样?【参考方案4】:

对于 Swift 4,您可以将 ++-- 运算符恢复为 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
    

其他类型的工作方式相同,例如UIIntInt8FloatDouble 等。

您可以将这些扩展粘贴到根目录中的单个文件中,它们将可在您那里的所有其他文件中使用。如果您在操场上查看它,它会完美运行。

【讨论】:

【参考方案5】:

Chris Lattner 与 ++ 和 -- 开战。他写道,“实际使用这些运算符的结果值的代码对于代码的读者/维护者来说往往是令人困惑和微妙的。他们鼓励“过于棘手”的代码,这些代码可能很可爱,但难以理解……虽然 Swift 有明确定义的评估顺序,但任何依赖它的代码(如 foo(++a, a++))都是不可取的,即使它是明确定义的……这些没有达到“如果我们还没有这些,我们会将它们添加到 Swift 3 中吗?”的度量标准

Apple 希望保持 swift 是一种干净、清晰、不混淆且直截了当的语言。所以他们弃用了 ++ 和 -- 关键字。

【讨论】:

干净吗?看看这个回调地狱并称其为干净?我不同意...而且我要补充一点:留下 ++ & -- 单独 ...for i in 0.stride(to: 10, by: 2)......for i in (1...10).reverse()... 这样的东西是干净的吗?! 我同意。 “干净”的论点与 Swift 的其余部分根本矛盾。来自客观上不干净的 Objective-C,很难接受“干净”作为 Apple 语言的目标。 尝试解析 json 和 swift 并告诉我它有多干净。【参考方案6】:

Xcode 的Fix-it feature 给出了明确的答案。

++ increment operator 替换为老式的value += 1(简写运算符),将-- decrement operator 替换为value -= 1

【讨论】:

【参考方案7】:

这是迄今为止发布的一些代码的通用版本。我会表达与其他人相同的担忧:在 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 类型的扩展。

【讨论】:

我在每个函数中添加了@discardableResult,以消除有关返回值未使用的警告;否则正是我想要的。【参考方案8】:

来自docs:

Swift 中的递增/递减运算符很早就添加了 Swift 的开发,作为 C 的继承。这些被添加 没有太多考虑,从那以后也没有考虑太多 然后。本文档提供了一个全新的视角,并最终 建议我们完全删除它们,因为它们令人困惑并且 没有承受他们的重量。

【讨论】:

也就是说这个操作太贵了不能用? github.com/apple/swift-evolution/blob/master/proposals/… 在这里你可以读到它,但这不是因为它很昂贵,而是因为它的语言设计。 所以我安徒生 Swift 将放弃对 C 风格特性的支持 @OlegGordiichuk 好吧,我想说他们想强调的是,与 Objective-C 不同,Swift 不是 C 的超集。 @mah 你说的很多东西根本没有意义。以什么方式“不面向现有开发者”?就像Java不面向php开发人员一样? “面向那些可能不想成为开发人员的人”?是的,因为所有那些非开发人员都在使用面向协议的编程和泛型。 “实现好的设计的一种方式” 看看 SO,你会发现没有任何编程语言可以“实现好的设计”。【参考方案9】:
var value : Int = 1

func theOldElegantWay() -> Int
return value++


func theNewFashionWay() -> Int
let temp = value
value += 1
return temp

这绝对是一个缺点,对吧?

【讨论】:

您的意思是优雅,就像“您必须记住 C 编程语言的所有细微之处,否则第一次调用返回 1 或 2 时不会立即明显”?我认为我们都可以节省几行额外的代码,以换取不用花几分钟摸索寻找由愚蠢错误引起的错误...【参考方案10】:

由于您在 Swift 中从未真正使用过指针,因此在我看来,删除 ++-- 运算符是有意义的。但是,如果您不能没有,您可以将这些 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

【讨论】:

【参考方案11】:

在没有分号的语言中,它可能是模棱两可的。是前缀还是后缀运算符?

考虑:

var x = y
++x

人类读取++x,但解析器可以将其读取为y++

【讨论】:

【参考方案12】:

在 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++ 等等。程序员乐于使用它。 无论谁太难理解这个运算符,他们并且只有他们应该使用 += (或者如果 += 也太复杂,也许 s = s + 1 )。

Swift 背后的策略很简单:Apple 认为程序员是愚蠢的,因此应该受到相应的对待。

事实上,2014 年 9 月推出的 Swift 到现在应该在其他地方。其他语言的发展速度要快得多。

我可以列出该语言中的许多主要错误,从严重的错误:例如按值而不是按引用粘贴的数组,到令人讨厌的错误:可变参数函数不能接受数组,这是其背后的全部思想。 我不认为 Apple 的员工甚至被允许查看其他语言,例如 Java,所以他们甚至不知道 Apple 落后了很多年。苹果本可以采用 Java 作为一种语言,但如今,挑战不是技术,而是自我。 如果他们会打开 IntelliJ 来编写一些 Java,那么他们肯定会关闭他们的业务,因为他们明白在这一点上,他们无法也永远不会赶上。

【讨论】:

以上是关于“++”和“--”运算符已被弃用 Xcode 7.3的主要内容,如果未能解决你的问题,请参考以下文章

kubectl (node:7) [MONGODB DRIVER] 警告:当前的服务器发现和监控引擎已被弃用,将在未来版本中删除

我是否需要更改我的Apps脚本代码,因为Google+登录功能已被弃用?

PageRequest 构造函数已被弃用

@angular-cli 安装失败,请求被弃用@2.88.2:请求已被弃用(mac)

为啥 InstanceMethods 模块已被弃用?

Spring RMI 的替代方案是啥? (因为它已被弃用)