Converting Between Types
A member types their distance into the club's web form: "10.5". That is text, and you cannot add text to a Double total. Scala converts between types in two different ways, and knowing which one applies saves you from both compile errors and crashes.
The rule
Safe widening happens by itself; anything that can lose or fail needs a
.toXcall.
Automatic widening. When the target type can hold every value of the source exactly, Scala converts silently:
val laps = 12
val bigLaps: Long = laps // Int to Long: automatic
val lapsD: Double = laps // Int to Double: automaticExplicit conversions. Everything else is a method you call:
8.9.toInt // 8: the decimal part is cut off, not rounded
math.round(8.9) // 9, returned as a Long
12.toDouble // 12.0
12.toString // "12"
'A'.toInt // 65, the character's code
66.toChar // 'B'The old automatic conversion from Int to Float is deprecated, because a Float cannot hold every Int exactly; write laps.toFloat instead.
Text to numbers. Parsing can fail, so decide what should happen when it does:
"10.5".toDouble // 10.5
"10,5".toDouble // throws NumberFormatException at run time
"10.5".toDoubleOption // Some(10.5)
"ten".toDoubleOption // None
"12".toIntOption // Some(12)toDouble and toInt assume the text is valid and throw if it is not. The Option versions return Some(value) or None, so a typo becomes a case you handle instead of a crash.
Narrowing without a call is a compile error: val laps: Int = 26.25 is rejected, because a Double cannot become an Int without losing its decimals.
The shortcut
Ask "can this lose information or fail?" If neither, just assign it and Scala widens. If it can lose information, call .toX and accept the loss knowingly. If it can fail, as text parsing always can, use the Option version whenever the text comes from a person.
The raw input
The form gives
"10.5", a String.
The trap is .toInt when you meant rounding: it cuts toward zero, so 8.9 becomes 8. Use math.round when you want the nearest whole number.
Drills
Answer fast — trust the rule.
Does val total: Double = 12 compile?
What is 8.9.toInt?
What happens when "10,5".toDouble runs?
What is "10,5".toDoubleOption?
Which line does the compiler reject?
Remember
- Lossless widening, such as Int to Long or Double, is automatic; everything else is a
.toXcall. - Ask "can it lose or fail?": lossy means
.toXon purpose; text from a person means theOptionversion. - Trap:
.toInttruncates, so usemath.roundto round.
