4

i am learning Swift with a book aimed for people with little experience. One thing bothering me is the ++ syntax. The following is taken from the book:

var counter = 0
let incrementCounter = {
  counter++
}
incrementCounter()
incrementCounter()
incrementCounter()
incrementCounter()
incrementCounter()

the book said counter is 5.

but i typed these codes in an Xcode playground. It is 4!

i am confused.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
Tang1230
  • 65
  • 1
  • 6
  • 1
    counter++ can be translated to counter = counter + 1, or counter += 1 – Shai Feb 29 '16 at 09:41
  • 4
    Note that the `++` and `--` operators [will be deprecated in Swift 2.2, and removed in Swift 3](https://github.com/apple/swift-evolution/blob/master/proposals/0004-remove-pre-post-inc-decrement.md). – dfrib Feb 29 '16 at 09:43
  • 3
    Don't worry about ++ and --. These operators are deprecated and will be removed from swift 3. – user965972 Feb 29 '16 at 09:44
  • 1
    because you are 'novice' in Swift, it would be better avoid to use ++ and / or -- operators. they will be removed from future versions of Swift language. instead use counter += 1 as recommended by Shai – user3441734 Feb 29 '16 at 09:46

6 Answers6

2

x++ operator is an operator that is used in multiple languages - C, C++, Java (see the C answer for the same question)

It is called post-increment. It increments the given variable by one but after the current expression is evaluated. For example:

var x = 1
var y = 2 + x++
// the value of x is now 2 (has been incremented)
// the value of y is now 3 (2 + 1, x has been evaluated before increment)

This differs from the ++x (pre-increment) operator:

var x = 1
var y = 2 + ++x
// the value of x is now 2 (has been incremented)
// the value of y is now 4 (2 + 4, x has been evaluated after increment)

Note the operator is getting removed in the next version of Swift, so you shouldn't use it anymore.

It's always better to just write x += 1 instead of complex expressions with side effects.

Community
  • 1
  • 1
Sulthan
  • 128,090
  • 22
  • 218
  • 270
2

The post-increment and post-decrement operators increase (or decrease) the value of their operand by 1, but the value of the expression is the operand's original value prior to the increment (or decrement) operation

So when you see playground, current value of counter is being printed.

playground

But after evaluation of function, the value of counter changes and you can see updated value on the next line.

saurabh
  • 6,687
  • 7
  • 42
  • 63
2

The value of counter after your five calls to the incrementCounter closure will be 5, but the return of each call to incrementCounter will seemingly "lag" one step behind. As Sulthan writes in his answer, this is due to x++ being a post-increment operator: the result of the expression will be returned prior to incrementation

var x = 0
print(x++) // 0
print(x)   // 1

Also, as I've written in my comment above, you shouldn't use the ++ and -- operators as they will be deprecated in Swift 2.2 and removed in Swift 3. However, if you're interested in the details of post- vs pre-increment operator, you can find good answers here on SO tagged to other languages, but covering the same subject, e.g.


It's worth mentioning, however, a point that is relevant to Swift > 2.1 however, and that don't really relate to the ++ operator specifically.

When you initiate the closure incrementCounter as

var someOne : Int = 0
let incrementCounter = {
    someInt
}

The closure is implictly inferred to be of type () -> Int: a closure taking zero arguments but with a single return of type Int.

let incrementCounter: () -> Int = {
    return someInt
}

Hence, what you seemingly "see" in you playground is the unused (non-assigned) return value of the call to incrementCounter closure; i.e., the result of the expression incrementCounter().

enter image description here

Whereas the value of counter is never really printed in the right block of your playground (unless you write a line where the result of that line:s expression is counter).

Community
  • 1
  • 1
dfrib
  • 70,367
  • 12
  • 127
  • 192
  • dfri, do you like the decision that unary ++ and / or -- will be remove from the language? see my 'answer' and notes to it, please :-) – user3441734 Feb 29 '16 at 10:39
  • @user3441734 You bring up some interesting points. However hopefully the type inference for closures will become even better in future Swift (e.g. your third code block should compile and infer closure as `() -> Int`). Personally I like making use of side effects and hence expressions incl. e.g. `++`, but I fully understand Swifts decision to remove these, as general code safety is a poster-child for Swift, and I believe they wish to include also safety against _logical_ errors in their scope. In such case, `++` and `--` poses some danger when used or code-read by less experienced programmers. – dfrib Feb 29 '16 at 10:46
2

++ and -- before the identifier add/subtract one, and then return its value.
++ and -- after the identifier return its value, and then add/subtract 1.

They were removed in Swift 3.0, but you can add them back:

prefix operator --
prefix operator ++
postfix operator --
postfix operator ++

prefix func ++(_ a : inout Int) -> Int {
    a += 1
    return a
}
prefix func --(_ a : inout Int) -> Int {
    a -= 1
    return a
}
postfix func ++(_ a: inout Int) -> Int {
    defer { a += 1 }
    return a
}
postfix func --(_ a: inout Int) -> Int {
    defer { a -= 1 }
    return a
}

var a = 11
print(a++) // 11
print(a)   // 12

var b = 5
print(--b) // 4
print(b) // 4

Sapphire_Brick
  • 1,560
  • 12
  • 26
1

even though there are a lot of answers and all of them are clear i added this snippet to show you how to replace your code with 'new' syntax, where ++ and or -- are deprecated. at first your own code

var counter = 0
let incrementCounter = {
    counter++
}
let i0 = incrementCounter() // 0
let i1 = incrementCounter() // 1
// .....

how to rewrite it in future Swift's syntax? lets try the recommended replacement ...

var counter = 0
let ic = {
    counter += 1
}
let i0 = ic() // () aka Void !!!
let i1 = ic() // ()

but now the result of ic() is Void! Hm ... OK, the next attempt could looks like

var counter = 0
let ic = {
    counter += 1
    return counter
}

but now the code doesn't compile with error: unable to infer closure return type in current context :-), so we have to declare it (it was not necessary in our original version)

var counter = 0
let ic:()->Int = {
    counter += 1
    return counter
}
let i0 = ic() // 1
let i1 = ic() // 2
// .....

it works, but the results are not the same. that is because in original code ++ operator was used as post-increment operator. so, we need another adjustment of our 'new' version

var counter = 0
let ic:()->Int = {
    let ret = counter
    counter += 1
    return ret
}
let i0 = ic() // 0
let i1 = ic() // 1
// .....

yes, i would like to see my familiar unary ++ and / or -- will be also in the future versions of Swift

user3441734
  • 16,722
  • 2
  • 40
  • 59
0

The thing which you are doing is post increment.

First Learn the difference between Pre & Post Increment

  1. In Post Increment, the value counter after increment contains incremented value (i.e 5) but if we return, then it will contain old value (i.e 4).
  2. In Pre Increment, both the value and return value is incremented.

Lets look into your code now,

counter++ makes a copy, increases counter, and returns the copy (old value).

so if you print counter it will have incremented value (i.e 5) but, if you return counter (i.e your doing so with incrementCounter) it contains the old value (i.e 4).

because of which incrementCounter only showing upto 4.

CHECK OUTPUT enter image description here Solution :

change counter++ to ++counter

CHECK OUTPUT enter image description here

aashish tamsya
  • 4,903
  • 3
  • 23
  • 34