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 outputs65536.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
Swift Running Code in Periodically Background
Abstract Class and Abstract Function in Swift
Arkit - Place a Scnplane Between 2 Vector Points on a Plane in Swift 3
How to Move an Object Towards a Direction Without Stopping
iOS Charts - Single Values Not Showing Swift
A Warning "'Init()' Is Deprecated". [Swift, iOS App, Learning Model]
Swift Spritekit Get Visible Frame Size
Heightanchor.Constraint Not Change Height of View
Why Is There Multiple Collision Calls Sprite Kit Swift
How to Properly Map JSON Properties to Model Properties in Realm.Create
Return Object for a Method Inside Completion Block
Can't Update Label from Other Class in Swift
Close Window Based on Kcgwindowname Value
How to Put a View with Loadmore Button in UItableview After The Cell
Why Does Editing a Textfield Throw a Nsinvalidargumentexception