The simpleName of String is literally "String":
scala> "abc".getClass.getSimpleName
res0: String = String
That makes sense, the simpleName of the type is the same name that I use to make one up in the first place, but consider Float:
scala> 32.2f
res4: Float = 32.2
scala> 23.2f.getClass.getSimpleName
res3: String = float
I was expecting 'Float' but I got '[f]loat' - why is the SimpleName behavior inconsistent with the representation of the object in the REPL?
Bonus points - is there a way that I can recover the exact name of the type I originally used, without any cumbersome mappings? What method is the REPL calling on the object to get it's correct name (with the capitol F).
The Scala type:
scala> import reflect.runtime._, universe._
import reflect.runtime._
import universe._
scala> def f[A](a: A)(implicit t: TypeTag[A]) = t
f: [A](a: A)(implicit t: reflect.runtime.universe.TypeTag[A])reflect.runtime.universe.TypeTag[A]
scala> f(2.0) // typeTag[Double]
res1: reflect.runtime.universe.TypeTag[Double] = TypeTag[Double]
scala> res1.tpe
res2: reflect.runtime.universe.Type = Double
scala> res2.typeSymbol.name
res3: reflect.runtime.universe.Symbol#NameType = Double
The boxed distinction is strictly an artifact of the underlying platform.
scala> java.lang.Float.TYPE
res4: Class[Float] = float
scala> classOf[java.lang.Float]
res5: Class[Float] = class java.lang.Float
What method is the REPL calling on the object to get it's correct name (with the capitol F).
It isn't calling any method on the object; if it did, it couldn't show two different types for the same object:
scala> val x = ""
res1: String = ""
scala> val y: Object = x
res2: Object = x
It's using compiler's information about types which can be accessed using TypeTags as som-snytt's answer shows.
Related
ClassTag only keeps the top level type of the type parameter, that is, given the following type: Seq[List[Int]],the type parameter is List[Int], but Only List is kept and Int is lost
def mkArray[T: ClassTag](data: T*) = Array(data: _*)
val data = Seq(List(1), List(2), List(3))
val arr = mkArray(data)
When calling mkArray to create an array, the Int for List[Int]should have been lost, so why the created array has the correct type of its elements,which is List[Int]
The underlying Java array knows the erased type of its elements at runtime. The compiler knows the precise time at compile-time.
scala> val xs = Array(List(1))
xs: Array[List[Int]] = Array(List(1))
scala> xs.getClass.getComponentType
res0: Class[_] = class scala.collection.immutable.List
scala> val vs = xs.asInstanceOf[Array[List[String]]]
vs: Array[List[String]] = Array(List(1))
scala> vs(0) = List("hi")
scala> xs
res2: Array[List[Int]] = Array(List(hi))
That information is lost at runtime, from type erasure, but not at compile time.
I toyed around with HList and the following works as expected:
val hl = 1 :: "foo" :: HNil
val i: Int = hl(_0)
val s: String = hl(_1)
However, I can't get the following piece of code working (let's assume for a moment random access on lists is a smart idea ;-)):
class Container(hl: HList) {
def get(n: Nat) = hl(n)
}
val container = new Container(1 :: "foo" :: HNil)
val i: Int = container.get(_0)
val s: String = container.get(_1)
I'd like to have get return an Int and String according to it's parameter. I assume, if possible at all, I have to use Aux or at but I'm not sure how to do this.
Try something along these lines,
scala> import shapeless._, nat._, ops.hlist._
import shapeless._
import nat._
import ops.hlist._
scala> class Container[L <: HList](hl: L) {
| def get(n: Nat)(implicit at: At[L, n.N]): at.Out = hl[n.N]
| }
defined class Container
scala> val container = new Container(1 :: "foo" :: HNil)
container: Container[shapeless.::[Int,shapeless.::[String,shapeless.HNil]]] = ...
scala> container.get(_0)
res1: Int = 1
scala> container.get(_1)
res2: String = foo
The first crucial difference here is that rather than typing hl as plain HList, which loses all specific information about the types of the elements, we parametrize over the precise type of the argument and preserve its structure as L. The second difference is that we use L to index the implicit At type class instance which is used to perform the indexing in get.
Also note that because there is an implicit conversion from Int literals to Nat's you can write,
scala> container.get(0)
res3: Int = 1
scala> container.get(1)
res4: String = foo
I have some Scala code that needs to call a Java API
The Java API takes arguments that may be null. My Scala, of course, uses Option.
For example, let's say I have a Java object constructor Foo(Integer) where the Integer may be null. I want to call it given a Scala bar: Option[Int].
I tried this
import scala.collection.JavaConversions._
import scala.collection.JavaConverters._
val foo = Foo( bar.getOrElse(null) )
But got this compile error
Error:(335, 44) type mismatch;
found : Any
required: Integer
bar.getOrElse(null),
What is the correct idiom for doing this?
You don't need a Java method to reproduce this problem:
scala> import scala.collection.JavaConversions._
import scala.collection.JavaConversions._
scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._
scala> class Foo(a: java.lang.Integer)
defined class Foo
scala> val bar: Option[Int] = Some(5)
bar: Option[Int] = Some(5)
scala> new Foo(bar.getOrElse(null))
<console>:16: error: type mismatch;
found : Any
required: Integer
new Foo(bar.getOrElse(null))
^
The problem is that Int can't be null, so the type of bar.getOrElse(null) is Any.
scala> bar.getOrElse(null)
res0: Any = 5
scala> bar.orNull
<console>:15: error: Cannot prove that Null <:< Int.
bar.orNull
^
So you've got to convert the Option's type parameter to something that can be null before you unwrap it in a nullable way.
Quickest way I can think of immediately:
scala> new Foo(bar.map(x => x: java.lang.Integer).orNull)
res18: Foo = Foo#cdc45e
Edit: Here, I thought of a more general way to do it!
implicit class RichOption[A](o: Option[A]) {
def toRef[B >: Null](implicit f: A => B): B = o.map(f).orNull
}
Now you can write new Foo(bar.toRef) :)
No sooner do I post the question, than I spot the answer in the related list (sorry)
Here's a solution
val foo = Foo(bar.getOrElse(null).asInstanceOf[java.lang.Integer])
Kind of clunky. Anyone have anything better?
More chatter:
scala> import runtime.BoxesRunTime.boxToInteger
import runtime.BoxesRunTime.boxToInteger
scala> val x = Some(42)
x: Some[Int] = Some(42)
scala> val y: Option[Int] = None
y: Option[Int] = None
scala> x.fold(null: Integer)(boxToInteger)
res0: Integer = 42
scala> y.fold(null: Integer)(boxToInteger)
res1: Integer = null
Of course it's better to
scala> x.fold(null: Integer)(i => i: Integer)
res2: Integer = 42
and even better
scala> x.fold[Integer](null)(identity)
res3: Integer = 42
scala> y.fold[Integer](null)(identity)
res4: Integer = null
Consider the following:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> typeOf[Boolean]
res23: reflect.runtime.universe.Type = Boolean
scala> typeOf[scala.Boolean]
res24: reflect.runtime.universe.Type = Boolean
scala> res23 == res24
res25: Boolean = true
scala> typeOf[java.lang.Boolean]
res26: reflect.runtime.universe.Type = Boolean
scala> res23 == res26
res27: Boolean = false
scala> class Foo { def bf(arg: Boolean) = ??? }
defined class Foo
scala> typeOf[Foo]
res28: reflect.runtime.universe.Type = Foo
scala> res28.member(newTermName("bf")).asMethod
res30: reflect.runtime.universe.MethodSymbol = method bf
scala> res30.paramss.head.head
res31: reflect.runtime.universe.Symbol = value arg
scala> res31.typeSignature
res32: reflect.runtime.universe.Type = scala.Boolean
scala> res32 == res23
res33: Boolean = false
scala> res32 =:= res23
res37: Boolean = true
So the type obtained via the typeOf[Boolean] function is equivalent to the type obtained via inspecting a method, but it is not equal.
Is there a way to transform two equivalent types into some canonical representation where the results will be equal? I'd like to be able to use them for things like keys in maps.
Edit:
To be more clear, what I'm looking for is something along the lines of (not a real repl session):
scala>val tp1 = // some type
scala>val tp2 = // equivalent type obtained another way
scala>tp1 == tp2
res1: Boolean = false
scala>tp1 =:= tp2
res2: Boolean = true
scala>val ctp1 = tp1.canonical
scala>val ctp2 = tp2.canonical
scala>ctp1 == ctp2
res3: Boolean = true
scala>ctp1 =:= tp1
res4: Boolean = true
scala>ctp2 =:= tp2
res5: Boolean = true
So equivalence is preserved by the transformation. I also need it to work on parameterized types.
From the documentation:
It's important to note that == should not be used to compare types for
equality—== can't check for type equality in the presence of type
aliases, while =:= can.
You can of course store the types in a list and use (for example) the following to check for inclusion:
myTypes.exists(_ =:= someType)
You'll see this approach in the 2.10 compiler source, for example. It's not as efficient as a map or set, of course, but you generally don't have many of these things in a collection.
If you absolutely have to have the performance of a map or set, you may be able to use erasure (as another answer suggests) or typeSymbol, depending on your requirements.
erasure method of scala.reflect.api.Types.TypeApi:
typeOf[Foo].member(newTermName("bf")).asMethod.paramss.head.head
.typeSignature.erasure == typeOf[Boolean]
// res21: Boolean = true
Is it possible to get the type of a type field after creating an object ?
I would like to do something like this:
scala> class A { type T = String }
defined class A
scala> val a = new A
a: A = A#591171
scala> a.T
<console>:13: error: value T is not a member of A
a.T
^
The last
What do you want to do with the type? You can use a type projection in various ways with the class's type (without an instance):
scala> class A { type T = String }
defined class A
scala> val x: A#T = "test"
x: java.lang.String = test
scala> def f(b: A#T) = b
f: (a: java.lang.String)java.lang.String
Or if you enable -Ydependent-method-types, you can get the type member from the instance:
scala> val a = new A
a: A = A#6a3de2df
scala> val x: a.T = "test"
x: a.T = test
scala> def f(b: a.T) = b
f: (b: a.T)a.T
Scala's reflection API prior to 2.10 doesn't really model types in any clean way, so if you want to "get the type" in some other sense, you're probably out of luck.
One way is with reflection (since 2.10M4):
// with static types
scala> class A { type T = String }
defined class A
scala> import reflect.runtime.{universe => u}
import reflect.runtime.{universe=>u}
scala> val t = u.typeOf[A]
t: reflect.runtime.universe.Type = A
scala> val types = t.declarations.filter(_.isType)
types: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(type T)
scala> types.toList.head.typeSignature
res9: reflect.runtime.universe.Type = String
// with instances
scala> val a = new A
a: A = A#68d7c870
scala> import reflect.runtime.{currentMirror => m}
import reflect.runtime.{currentMirror=>m}
scala> m.reflect(a).symbol.asType // same type as t
res20: reflect.runtime.universe.Type = A