I have the following method:
def toNumber[T <: AnyVal](value:String, default:T)(implicit n: Numeric[T]):T = {
val str = value.trim
var s = n.zero
if (value.trim.isEmpty) {
default
} else {
if (default.isInstanceOf[Long])
s = n.plus(n.zero,str.toLong.asInstanceOf[T])
else if (default.isInstanceOf[Int])
s = n.plus(n.zero,str.toInt.asInstanceOf[T])
}
s
}
Is it possible to streamline this somehow so it looks at the type of T (e.g. Int, Long, etc.) and uses it to call the right "to" method (e.g. toInt, toLon开发者_StackOverflow社区g, etc.)?
As a bonus question, can I somehow limit T to just Int and Long rather than any subclass of AnyVal?
Thanks, John
If you want to limit T
to specific numeric instances, it might be a good idea to provide your own typeclass (thus providing an answer to your initial question):
trait Natural[T] { def from(s : String) : T }
implicit object IntNatural = new Natural[Int] {
def from(s : String) = s.toInt
}
implicit object LongNatural = new Natural[Long] {
def from(s : String) = s.toLong
}
Then your method:
def toNumber[T : Natural](value : String, default : T) : T =
if (value.trim.isEmpty)
default
else
implicitly[Natural[T]].from(value.trim)
However, I would personally re-write this method signature as:
def natural[T : Natural](value : String) : Option[T]
And then users would use getOrElse default
at the use-site. For example:
natural[Int]("42") getOrElse 23
精彩评论