How Does Swift's Int Literal to Float Inference Work

How does Swift's int literal to float inference work?

Literals don't have a type as such. The docs say,

If there isn’t suitable type information available, Swift infers that the
literal’s type is one of the default literal
types defined in the Swift standard library. The default types are Int
for integer literals, Double for floating-point literals, String for
string literals, and Bool for Boolean literals.

So unless your argument explicity says anything other than Int, it will infer integer literals as Int.


Refer this for more information, Lexical Structure - Literals.

Why Int and Float literals are allowed to be added, but Int and Float variables are not allowed to do the same in Swift?

In case of var sum = 4 + 5.0 the compiler automatically converts 4 to a float as that is what is required to perform the operation.
Same happens if you write var x: Float = 4. The 4 is automatically converted to a float.

In second case, since you have explicitly defined the type of the variable, the compiler does not have the freedom to change is as per the requirement.

For solution, look at @Fabio 's answer

Why is Swift inferring double values when using literals?

"Cast" is not really the right word here. It interprets the character sequence "4" and "2" as an integer literal. Double conforms to ExpressibleByIntegerLiteral, so the Double can be constructed from it.

fortyTwoInt is not an integer literal. It's an Int. And Swift will not automatically convert between Int and Double.

Why is Swift inferring double values when using literals?

"Cast" is not really the right word here. It interprets the character sequence "4" and "2" as an integer literal. Double conforms to ExpressibleByIntegerLiteral, so the Double can be constructed from it.

fortyTwoInt is not an integer literal. It's an Int. And Swift will not automatically convert between Int and Double.

Type inference issue with Swift's Double initializer for shifted integer parameters

This looks like a bug in the compiler. As @Hamish said, the latest master has this problem fixed, I can confirm that as I have the toolchains for Swift 4.2 and Swift 5.0 installed:

  • with the Swift 4.2 toolchain the behaviour is as you described: the first print outputs 0.0, while the second one outputs 65536.0
  • while if using the latest Swift 5.0 toolchain, both calls print 65536.0

Understanding the Doubles and Ints in Swift

As you know, Swift is very strict with types, but there's one area where it's not so strict - literals. Double conforms to ExpressibleByIntegerLiteral, so you could do:

let x: Double = 1 // "1" is "magically" converted to a Double!?

and have it compile. The same with arrays - the compiler thinks that the array literal that you have:

[50, 5.0, 10]

is a [Double], because it can convert both 50 and 10 to Double. It can't be an [Int] because 5.0 can't be converted to an Int (Int does not conform to ExpressibleByFloatLiteral)

The line:

total += amounts[i]

only works when both sides are of the same type. Note that here, the compiler will not try to convert from Int to Double because the expressions involved (total and amounts[i]) are not literals!

If you change the array literal to [50, 10, 10], all elements are Int, so the compiler infers the array to be [Int], and amount[i] becomes an Int, causing the line to fail compilation.

Understanding the rules for conversion in swift

4 is not a "value". It is a literal. So it can be interpreted however Swift likes. There is nothing to "convert"; it is used to create the value, but the created value will be a Float, because that is what you asked for.

But now try this:

let i : Int = 4
let mynum: Float = i

Ooooops.

To put it another way:

let mynum: Float = 4

is interpreted as

let mynum = Float(4) // we are _creating_ the value

But if we start with i, you have to create the value:

let i : Int = 4
let mynum: Float = Float(i)

Swift won't do that for you.

BONUS LESSON Hold my beer and watch this:

struct Dog : IntegerLiteralConvertible {
var number : Int?
init(integerLiteral: Int) {
self.number = integerLiteral
}
}
let dog : Dog = 42

Float works like that, sort of.



Related Topics



Leave a reply



Submit