'Double modulo' operator

I agree (that it was a mistake not to include all three variants, and that it's too source breaking to change the semantics of %).

Also, note that changing the behavior of % would also break code for people (like me) who needed the floored or euclidean definition, and rolled their own, perhaps based on Swift's %.


Regarding how people (mis)use Swift's %. The following are some results of a quick search I did to see if I could find any examples of the common pitfall mentioned in the wikipedia article:

1:

let isOdd : (Int) -> Bool = { $0 % 2 == 1 }

This will return false for every negative number.

Found here: Transducers & Reducers in Swift 2 · GitHub


2:

func isOdd(number: Int) -> Bool {
    if number % 2 == 1 {
        return true
    } else {
        return false
    }
}

Same thing but more verbose.

Found here: Chapter 7: Functions - We ❤ Swift


3:

For example, imagine you wanted to compute a sum similar to that of triangle numbers, but only for odd numbers:

let count = 10
var sum = 0
for i in 1...count where i % 2 == 1 {
    sum += i
}

Not strictly wrong since i is in the range 1 ... count, but it must be considered bad practice to not write i % 2 != 0 instead, and it makes it seem like they misunderstand Swift's %.

Found here: Swift Tutorial Part 3: Flow Control | Kodeco


4:

The remainder operator is most useful when checking the parity, or “evenness,” of a number. If we wanted to know if a number x is even, we can use the remainder operator and check if the result is 0 or 1: x % 2 . If that result is 0, then we know that the number is even; if the result is 1, then we know the number is odd.

They recommend a method to check for odd numbers that will not work for negative numbers. If they had known how % worked, they would have wrote: "if the result is not 0, then we know the number is odd".

Found here: https://swiftludus.org/how-to-use-operators-in-swift/


My guess is that the % operator is widely misunderstood and misused (not just in Swift).

Including methods for all three (truncated, floored, euclidean) in the standard library would not only provide us with frequently needed functionality, but also help increase the awareness of their existence and differences.

10 Likes