Edit: I updated the solution to parse from any type to any type. This makes the solution more generic based on the question requested. I think you can use Scala functional way to have the generic type [T] but you need to split it into two parts.
First to implement parse types which parses from any type [U] to
any type [T]. parseTypes takes a function canBuildFrom as a parameter using Scala functional way. Then based on the output of this function you will checks if it parsed correctly or it has an exception. Also, in case it failed to parse you can pass a default parameter.
def parseTypes[T,U](str: U, canBuildFrom: U ⇒ T): Either[java.lang.NumberFormatException, T] =
Try(canBuildFrom(str)).map(Right(_)).getOrElse {
Left(new java.lang.NumberFormatException(str.toString))
}
def safeParse[T,U](attributeValue: U, canBuildFrom: U ⇒ T, defaultValue: T): T = {
parseTypes(attributeValue, canBuildFrom) match {
case Right(x) ⇒ x
case Left(x) ⇒ defaultValue
case _ ⇒ defaultValue
}
}
def safeParseDoubleToBigDecimal(attributeValue: Double): BigDecimal = safeParse[BigDecimal,Double](attributeValue, toBigDecimal, 0.0)
You can use it to parse String to Int, Double, and Decimal as following:
def safeParseStringToInt(attributeValue: String): Int = safeParse[Int,String](attributeValue, _.toInt, 0)
def safeParseStringToDouble(attributeValue: String): Double = safeParse[Double ,String](attributeValue, _.toDouble, 0.0)
def safeParseStringToBigDecimal(attributeValue: String): BigDecimal = safeParse[BigDecimal ,String](attributeValue, BigDecimal(_), 0.0)
// example of usage
val x:Int = safeParseStringToInt("123",0)
val y:Int = safeParseStringToInt("aaa",0)
Update: I update this answer as I realized that @Dima's answer is somehow more functional and better than my answer I added the answer below copied from @Dima's answer as my answer marked as the correct answer.
trait ParseIt[T] {
protected def parse(s: String): T
def apply(s: String) = Try(parse(s)).toOption
}
implicit object ParseInt extends ParseIt[Int] {
protected def parse(s: String) = s.toInt
}
implicit object ParseDouble extends ParseIt[Double] {
protected def parse(s: String) = s.toDouble
}
// etc ...
def parse[T : ParseIt](s: String, orElse: => T) =
implicitly[ParseIt[T]](s).getOrElse(orElse)
val n: Int = parse("123", 0)
val d: Double = parse("123", 0.0)
.toIntor.toDouble. But why typeclass is better solution? The solution related tosafeParsedo it correctly without any drawback. - Sa2012