Why does swift behave so weird when comparing Doubles and Integers?
Consider the following code for repl/playground:
12>12.0 //false
13 > 12.0 //true
13.0 > 12 //true
13 >= 12.0 //true
13 <= 12.0 //false
12.0 < 13 //Error: Ambiguous use of operator '<'
12 < 13.0 //Error: Ambiguous use of operator '<'
What exactly is Ambiguous in the use of operator here?
The debug console output is not especially helpful either:
error: ambiguous use of operator '<'
12 < 13.0
^
Foundation.RunLoop:18:32: note: found this candidate
public static func < (lhs: RunLoop.SchedulerTimeType.Stride, rhs: RunLoop.SchedulerTimeType.Stride) -> Bool
^
Foundation.Decimal:4:24: note: found this candidate
public static func < (lhs: Decimal, rhs: Decimal) -> Bool
^
Foundation.OperationQueue:18:32: note: found this candidate
public static func < (lhs: OperationQueue.SchedulerTimeType.Stride, rhs: OperationQueue.SchedulerTimeType.Stride) -> Bool
^
Dispatch.DispatchQueue:22:32: note: found this candidate
public static func < (lhs: DispatchQueue.SchedulerTimeType.Stride, rhs: DispatchQueue.SchedulerTimeType.Stride) -> Bool
UPD: Just to clarify, I know that I can cast values explicitly.
The question is why exactly does the language behave this way and was is it designed to behave this way with <
operator?
CodePudding user response:
I think operators >, >=, =, != were implemented by Swift's cast mechanism to compare. Operator <, == are two special operators which must be of the same type to compare.
I found a Swift Document, which has some information about it. Compare
CodePudding user response:
The first thing to note is you are not comparing Double
s to Int
s. All of your examples compare two literals and I expect that Swift is inferring the types to be Double
always. You can verify this with the following
let a: Int = 12
a > 12.0 // Error: Binary operator > cannot be applied to Int and Double
The second thing to note is that the problem goes away if you do not import Foundation
.
What is actually happening is that Foundation
introduces several overloads for <
in order to make a number of Foundation types conform to Comparable
and the compiler no longer knows which type to infer when compiling comparisons of literals (it must also be making these types conform to ExpressibleByFloatliteral
and ExpressibleByIntegerLiteral
) .
The reason that it is only for <
is probably due to the fact that you only need to implement that operator to conform to Comparable
and there are default implementations for the other comparison operators in an extension to the protocol.