Suppose I have:
val number:AnyVal
and I know x may be any number (for our purposes, a Float, Double, Int, Long).
What's the easiest way to convert such a number to a Long:
val l = number.toLong //fails for AnyVal
You can cast it to a Number if you know it's definitely going to be a Float, Double, Int, or Long. Then you can call longValue:
val number:AnyVal = 10
val l:Long = number.asInstanceOf[Number].longValue
How about:
scala> import scala.util.Try
import scala.util.Try
scala> val i1: Int = 23
i1: Int = 23
scala> val l1: Long = 42
l1: Long = 42
scala> val f1: Float = 14.9f
f1: Float = 14.9
scala> val d1: Double = 14.96
d1: Double = 14.96
scala> val b1: Boolean = true
b1: Boolean = true
scala> List(i1, l1, f1, d1, b1) map (x => Try(x.asInstanceOf[Number].longValue)) foreach (println(_))
Success(23)
Success(42)
Success(14)
Success(14)
Failure(java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Number)
scala> List(i1, l1, f1, d1, b1) map (x => Try(x.asInstanceOf[Number].longValue)) foreach (n => println(n.get))
23
42
14
14
java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Number
at $anonfun$1$$anonfun$apply$1.apply$mcJ$sp(<console>:14)
at $anonfun$1$$anonfun$apply$1.apply(<console>:14)
at $anonfun$1$$anonfun$apply$1.apply(<console>:14)
at scala.util.Try$.apply(Try.scala:161)
at $anonfun$1.apply(<console>:14)
at $anonfun$1.apply(<console>:14)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at .<init>(<console>:14)
Updated answer for Scala 2.11
My original answer does not work in newer versions of Scala because the implicit conversion to RichLong is no longer available.
This updated version works for numbers via type matching for Number sub-types and also for Strings via an implicit conversion in Scala 2.11:
object LongNumber {
def cast(number: Any): Long = number match {
case n: Number => n.longValue()
case x => throw new IllegalArgumentException(s"$x is not a number.")
}
// Test cases
def main(args: Array[String]): Unit = {
val twelveByte: Byte = 0x0c
val twelveString: String = "12"
println(s"Converting a long: ${cast(12L)}")
println(s"Converting an int: ${cast(12)}")
println(s"Converting a double: ${cast(12.0)}")
println(s"Converting a byte: ${cast(twelveByte)}")
println(s"Converting a string: $twelveString")
}
}
The matching technique is a minor variation on the casting technique used in other answers.
Original answer for older versions of Scala
Attempting implicit conversion to RichLong in a match block seems to work quite nicely:
import scala.runtime.RichLong
...
def cast(number: Any): Long = number match {
case n: RichLong => n.toLong
case x => throw new IllegalArgumentException(s"$x is not a number.")
}
It might also be possible to add a case for matching a String in numeric format if you wanted to cater for that possibility.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With