Scala generic cast from String function -
how can write function convert string generic type (double, int, float, etc.)?
here's pseudocode functionality i'm looking for:
def castfromstring[a: manifest](value: string): = { if (a == double) { parsedouble(value) } else if (a == int) { parseint(value) } else { value.tostring() } }
i don't think there way write function such manifest, classtag or typetag can tell type @ runtime. pseudocode function work, return type must known @ compile time.
however, implement function defining type class , writing instances types wish cast from. here's example:
import java.lang.double.parsedouble import java.lang.integer.parseint trait castablefromstring[a] { def fromstring(string: string): } object castablefromstring { implicit object doublecastablefromstring extends castablefromstring[double] { override def fromstring(string: string): double = parsedouble(string) } implicit object intcastablefromstring extends castablefromstring[int] { override def fromstring(string: string): int = parseint(string) } implicit object intlistcastablefromstring extends castablefromstring[list[int]] { override def fromstring(string: string): list[int] = string.split(',').map(parseint).tolist } def castfromstring[a](string: string)(implicit cast: castablefromstring[a]): = cast.fromstring(string) } object main { import castablefromstring._ def main(args: array[string]): unit = { val d = castfromstring[double]("4.5") val = castfromstring[int]("42") val li = castfromstring[list[int]]("1,2,3") println(s"d=$d i=$i li=$li") } } alternatively, closer resembles pseudocode, use macro. here's example (won't work on older scala 2.11):
import scala.language.experimental.macros import scala.reflect.macros.blackbox.context class stringcasterimpl(val c: context) { def castfromstringimpl[a: c.weaktypetag](string: c.expr[string]): c.tree = { import c.universe._ val t = c.weaktypeof[a] if (t =:= typeof[double]) { q"java.lang.double.parsedouble($string)" } else if (t =:= typeof[int]) { q"java.lang.integer.parseint($string)" } else if (t =:= typeof[list[int]]) { q"$string.split(',').map(java.lang.integer.parseint).tolist" } else { c.abort(c.enclosingposition, s"don't know how cast $t string") } } } object stringcaster { def castfromstring[a](string: string): = macro stringcasterimpl.castfromstringimpl[a] } // note object must in separate compilation unit object main { import stringcaster._ def main(args: array[string]): unit = { val d = castfromstring[double]("4.2") val = castfromstring[int]("42") val li = castfromstring[list[int]]("1,2,3") println(s"d=$d i=$i li=$li") } }
Comments
Post a Comment