How can I cast a a string to generic number using scala? - scala

I'm trying to convert a generic string to a number using scala
object h extends App {
def castTo[T](s: String): T = {
s.asInstanceOf[T]
}
print(castTo[Int]("20"))
print(castTo[Double]("20.1"))
}
the data:
name | value
a | "1"
b | "2.123"
c | "abd"
the usecase:
riight now I'm exporting the data to the user a method for each conversion.
getNameAsDouble, getNameAsInteger and so forth.
I wish to do getNameT to save lot's of code and make it a bit more pretty and easy to read the doc.
so, in case a programmer does :
getNameInt i want the program to print in this case: 1
getNameDouble i want the program to print in this case: 2.123
in cpp i could use dynamic_cast. there a way to do so in scala?
( i also tried to do so in java but couldn't find a way)
p.s.
i've tried something like this, but i wandered if there is more generic way.
castTo[T] (s:String): T = {
...
case T instance of Integer => s.toInt
case T instance of Long => s.toLong
...
}

I believe it would be better if you can expand more on your use case.
But, this should do what you want.
def readAs[T](str: String)(implicit num: Numeric[T]): Option[T] =
num.parseString(str)
Which you can test like:
readAs[Int]("10")
// res: Option[Int] = Some(10)
readAs[Double]("10")
// res: Option[Double] = Some(10.0)
readAs[Double]("10.0d")
// res: Option[Double] = Some(10.0)
readAs[Int]("10.0d")
// res: Option[Int] = None
readAs[Int]("blah")
// res: Option[Int] = None

Scala is not javascript. Scala is a real programming language with types. Strong types even. So, it treats conversions between types as what they really are: conversions. Not "casts". So, the string will have to be parsed into a number. And if you wrap this parsing in a function, it is utterly wrong to call this conversion a "cast".
And no, you cannot cast a string to a number in C++ either. Not with a dynamic cast, nor with any other kind of cast. You also have to parse it in C++, because C++ is also a real programming language.
As for simplifying your pattern matching expression, you might be able to first parse the string into a double, and then use a generic cast to convert that double into a number of lesser precision, but I do not have a Scala compiler at hand to prove the concept.

Related

Why can I concatenate String and Int in Scala?

I'm trying out some things in Scala, coming from Python. Since Scala is a lot more strict about keeping types consistent, I was surprised to find out that I can do the following concatenation, which would blow up in Python:
def adder(one:Any, two:String) = {one+two}
adder("word", "suffix")
res13: String = wordsuffix
But also:
val x:Int = 1
adder(x, "suffix")
res12: String = 1suffix
So it just transforms an Int into a String w/out telling me. What is this called and what is the logic behind it?
And what is the benefit of this? I feel it can come back to bite me, e.g. when dealing with user input to a function.
I know this is not very specific and if this is too broad, I'll gladly retract the question.
There is an implicit class in scala.Predef that operates on objects of any type
implicit final class any2stringadd[A](private val self: A) extends AnyVal {
def +(other: String): String = String.valueOf(self) + other
}
That implements Any + String (as you have defined it in adder). As rogue-one mentioned, there is also a method for concatenating String + Any defined in StringOps. If you tried to do Any + Any it would fail because it's expecting a String as the argument.
So it just transforms an Int into a String w/out telling me
Scala is converting your Int into a String, but it's not a type conversion because Int cannot be coerced into a String. You can observe that by trying something like this:
def foo(str: String) = ???
foo(5) // Type mismatch: expected: String, actual: Int
That will fail to compile because Scala can't magically coerce an Int into a String.
what is the logic behind it?
See implicit classes
And what is the benefit of this? I feel it can come back to bite me, e.g. when dealing with user input to a function.
It's a convenience method that's very specific to String and concatenation. This feature is implemented in Java, so I believe it was implemented in Scala to maintain source compatibility. My example above shows that (except in this specific case), user input to a function will respect the types defined on the function.
It's called implicit conversion (or implicit typecasting)
The purpose - convenience so you don't have to do everything manually. Most high-level languages will do that with the most used generics like strings, ints, bools...
You can check scala.Predef to see all the methods used when implicitly converting types, and you can take control of it using scala.language.implicitConversions. Read more at Scala Documentation.
This String concatenation not only works for Int but for any data-type. For instance
scala> case class Elephant(value: String)
defined class Elephant
scala> "Hello" + Elephant("elephant")
res2: String = HelloElephant(elephant)
This is because of the method + defined in StringOps (via Predef) class that accepts argument of type Any. So it is a method that is made available to a String object via implicit conversion that takes an argument of type Any. so "Hello" + Elephant("elephant") is actually "Hello".+(Elephant("elephant"))

How do I write a shorthand for a datatype in Scala

How do I write shorthand for a datatype?
For example.
lets say instead of List[Integer], I would rather type Integers
instead of this
def processNumbers(input:List[Integer]):List[Integer] = ...
to
def processNumbers(input:Integers):Integers = ...
Is this possible?
Thanks
Yes, you can do this with a type alias.
type Integers = List[Int] // scala.Int is preferred over java.lang.Integer
That being said, this isn't really a good use for them. List[Int] is very clear to other scala developers, wheres your type Integers provides no extra information and so will detract from the readability of your code over time.
A use of type aliases that would improve your code's readability though would be something like
type UserId = Int
def processUsers(ids: List[UserId]): Foo
In this case it provides extra information to the reader vs
def processUsers(ids: List[Int]): Foo
Using that kind of type alias also will allow you to gradually make your code more type-safe over time by changing the definition from a type alias to a value class.
case class UserId(value: Int) extends AnyVal
You won't need to change the method signatures of anything already having "UserId", but this will let the compiler assist you in making sure you don't do something like
val ids: List[Int] = getBlogPostIds()
val foo = processUsers(ids) // Oops, those Ints are for blog posts, not users
Using the value class approach, a mistake like that becomes a compiler error. Used pervasively it adds quite a lot of guidance in writing correct code.
val ids: List[BlogPostId] = getBlogPostIds
val foo = processUsers(ids) // Compile error; BlogPostId != UserId

scala simple example of proper subtyping

I'm new to scala and trying to understand the right way to think about subtypes, so here's a simple example.
Let's say I want to make a function truncation() that takes a number and rounds it down to a few decimals places and returns the result. I might go about this as,
def truncation(number:Double, level:Int)={
math.floor(number * math.pow(10,level)) / math.pow(10,level)
}
truncation(1.2345, 2)
res0: Double = 1.23
But I probably also want this function to work with other numeric types besides Double, such as Float.
So how should I think about generalizing this function to work well with multiple types?
I'm thinking I should be using generic types such as
def truncation [A](number:A, level:Int):A={
math.floor(number * math.pow(10,level)) / math.pow(10,level)
}
but this doesn't compile.
In the case of just two types, I see that the Either type is a good option. But in the more general case,maybe I'll want to be able to handle Ints as well, and have different implementations that match on the type of the input object.
What's the best way to be thinking about this? Thanks for your help.
For a generic that you want to constrain to numeric types, you can use Numeric:
def truncation[T](number: T, level:Int)(implicit n: Numeric[T]) = {
import math._
val doubleValue = n.toDouble(number)
floor(doubleValue * pow(10,level)) / pow(10,level)
}
Or equivalently:
def truncation[T : Numeric](number: T, level:Int) = {
import math._
val doubleValue = implicitly[Numeric[T]].toDouble(number)
floor(doubleValue * pow(10,level)) / pow(10,level)
}
These will work for Ints, Doubles, Floats, and other numeric types.
The first example uses an implicit parameter, which you can read about here. The second version uses a context bound, which you can read about here together with the implicitly operator, which you can read about here. Finally, read the documentation of Numeric here to see all the available methods.
Note that the versions above both return Double. If you want them to return T (whatever the input type is), you can try:
def truncation[T : Numeric](number: T, level:Int): T = implicitly[Numeric[T]] match {
case n:Fractional[T] =>
val tenPow = n.fromInt(math.pow(10, level).toInt)
n.div(n.fromInt(n.toInt(n.times(number, tenPow))), tenPow)
case n:Integral[T] => number
}

What is the best way to create and pass around dictionaries containing multiple types in scala?

By dictionary I mean a lightweight map from names to values that can be used as the return value of a method.
Options that I'm aware of include making case classes, creating anon objects, and making maps from Strings -> Any.
Case classes require mental overhead to create (names), but are strongly typed.
Anon objects don't seem that well documented and it's unclear to me how to use them as arguments since there is no named type.
Maps from String -> Any require casting for retrieval.
Is there anything better?
Ideally these could be built from json and transformed back into it when appropriate.
I don't need static typing (though it would be nice, I can see how it would be impossible) - but I do want to avoid explicit casting.
Here's the fundamental problem with what you want:
def get(key: String): Option[T] = ...
val r = map.get("key")
The type of r will be defined from the return type of get -- so, what should that type be? From where could it be defined? If you make it a type parameter, then it's relatively easy:
import scala.collection.mutable.{Map => MMap}
val map: MMap[String, (Manifest[_], Any) = MMap.empty
def get[T : Manifest](key: String): Option[T] = map.get(key).filter(_._1 <:< manifest[T]).map(_._2.asInstanceOf[T])
def put[T : Manifest](key: String, obj: T) = map(key) = manifest[T] -> obj
Example:
scala> put("abc", 2)
scala> put("def", true)
scala> get[Boolean]("abc")
res2: Option[Boolean] = None
scala> get[Int]("abc")
res3: Option[Int] = Some(2)
The problem, of course, is that you have to tell the compiler what type you expect to be stored on the map under that key. Unfortunately, there is simply no way around that: the compiler cannot know what type will be stored under that key at compile time.
Any solution you take you'll end up with this same problem: somehow or other, you'll have to tell the compiler what type should be returned.
Now, this shouldn't be a burden in a Scala program. Take that r above... you'll then use that r for something, right? That something you are using it for will have methods appropriate to some type, and since you know what the methods are, then you must also know what the type of r must be.
If this isn't the case, then there's something fundamentally wrong with the code -- or, perhaps, you haven't progressed from wanting the map to knowing what you'll do with it.
So you want to parse json and turn it into objects that resemble the javascript objets described in the json input? If you want static typing, case classes are pretty much your only option and there are already libraries handling this, for example lift-json.
Another option is to use Scala 2.9's experimental support for dynamic typing. That will give you elegant syntax at the expense of type safety.
You can use approach I've seen in the casbah library, when you explicitly pass a type parameter into the get method and cast the actual value inside the get method. Here is a quick example:
case class MultiTypeDictionary(m: Map[String, Any]) {
def getAs[T <: Any](k: String)(implicit mf: Manifest[T]): T =
cast(m.get(k).getOrElse {throw new IllegalArgumentException})(mf)
private def cast[T <: Any : Manifest](a: Any): T =
a.asInstanceOf[T]
}
implicit def map2multiTypeDictionary(m: Map[String, Any]) =
MultiTypeDictionary(m)
val dict: MultiTypeDictionary = Map("1" -> 1, "2" -> 2.0, "3" -> "3")
val a: Int = dict.getAs("1")
val b: Int = dict.getAs("2") //ClassCastException
val b: Int = dict.getAs("4") //IllegalArgumetExcepton
You should note that there is no real compile-time checks, so you have to deal with all exceptions drawbacks.
UPD Working MultiTypeDictionary class
If you have only a limited number of types which can occur as values, you can use some kind of union type (a.k.a. disjoint type), having e.g. a Map[Foo, Bar | Baz | Buz | Blargh]. If you have only two possibilities, you can use Either[A,B], giving you a Map[Foo, Either[Bar, Baz]]. For three types you might cheat and use Map[Foo, Either[Bar, Either[Baz,Buz]]], but this syntax obviously doesn't scale well. If you have more types you can use things like...
http://cleverlytitled.blogspot.com/2009/03/disjoint-bounded-views-redux.html
http://svn.assembla.com/svn/metascala/src/metascala/OneOfs.scala
http://www.chuusai.com/2011/06/09/scala-union-types-curry-howard/

Pattern matching a String as Seq[Char]

In Scala it is possible formulate patterns based on the invididual characters of a string by treating it as a Seq[Char].
An example of this feature is mentioned in A Tour of Scala
This is the example code used there:
object RegExpTest1 extends Application {
def containsScala(x: String): Boolean = {
val z: Seq[Char] = x
z match {
case Seq('s','c','a','l','a', rest # _*) =>
println("rest is "+rest)
true
case Seq(_*) =>
false
}
}
}
The problem I have with this is the third line of the snippet:
val z: Seq[Char] = x
Why is this sort of cast necessary? Shouldn't a String behave like a Seq[Char] under all circumstances (which would include pattern matching)? However, without this conversion, the code snippet will not work.
There is some real abuse of terminology going on in the question and the comments. There is no cast in this code, and especially "So basically, this is a major concession to Java interoperability, sacrificing some type soundness" has no basis in reality.
A scala cast looks like this: x.asInstanceOf[Y].
What you see above is an assignment: val z: Seq[Char] = x
This assignment is legal because there is an implicit conversion from String to Seq[Char]. I emphasize again, this is not a cast. A cast is an arbitrary assertion which can fail at runtime. There is no way for the implicit conversion to fail.
The problem with depending on implicit conversions between types, and the answer to the original question, is that implicit conversions only take place if the original value doesn't type check. Since it's perfectly legal to match on a String, no conversion takes place, the match just fails.
Not 100% sure if this is correct, but my intuition says that without this explicit cast you would pattern match against java.lang.String, which is not what you want.
The explicit cast forces the Scala compiler to use Predef.stringWrapper implicit conversion; thus, as RichString extends Seq[Char], you are able to do a pattern match as if the string were a sequence of characters.
I'm going to echo everything that andri said. For interoperability, Scala strings are java.lang.Strings. In Predef, there's an implicit conversion from String to RichString, which implements Seq[Char].
A perhaps nicer way of coding the pattern match, without needing an intermediate val z to hold the Seq[Char]:
def containsScala(x: String): Boolean = {
(x: Seq[Char]) match {
...
}
}