I've wrapped a Message and would like to log which message I've wrapped.
val any :Any = msg.wrappedMsg
var result :Class[_] = null
The only solution I could find is matching everything:
result = any match {
case x:AnyRef => x.getClass
case _:Double => classOf[Double]
case _:Float => classOf[Float]
case _:Long => classOf[Long]
case _:Int => classOf[Int]
case _:Short => classOf[Short]
case _:Byte => classOf[Byte]
case _:Unit => classOf[Unit]
case _:Boolean=> classOf[Boolean]
case _:Char => classOf[Char]
}
I wonder if there's a better solution?
The following 2 approaches do not work :(
result = any.getClass //error
// type mismatch; found : Any required: ?{val getClass: ?}
// Note: Any is not implicitly converted to AnyRef.
// You can safely pattern match x: AnyRef or cast x.asInstanceOf[AnyRef] to do so.
result = any match {
case x:AnyRef => x.getClass
case x:AnyVal => /*voodoo to get class*/ null // error
}
//type AnyVal cannot be used in a type pattern or isInstanceOf
You can safely call .asInstanceOf[AnyRef] on any Scala value, which will box primitives:
scala> val as = Seq("a", 1, 1.5, (), false)
as: Seq[Any] = List(, 1, 1.5, (), false)
scala> as map (_.asInstanceOf[AnyRef])
res4: Seq[AnyRef] = List(a, 1, 1.5, (), false)
From there, you can call getClass.
scala> as map (_.asInstanceOf[AnyRef].getClass)
res5: Seq[java.lang.Class[_]] = List(class java.lang.String, class java.lang.Int
eger, class java.lang.Double, class scala.runtime.BoxedUnit, class java.lang.Boo
lean)
Tested with 2.8.0.RC6, I don't know it this worked in 2.7.7.
Definitely new in 2.8 are the companion objects for the classes derived from AnyVal. They contain handy box and unbox methods:
scala> Int.box(1)
res6: java.lang.Integer = 1
scala> Int.unbox(res6)
res7: Int = 1
Won't casting just do the trick, as suggested in the error message?
scala> val d:Double = 0.0
d: Double = 0.0
scala> d.asInstanceOf[AnyRef].getClass
res0: java.lang.Class[_] = class java.lang.Double
As of scala 2.10.0, getClass is available on Any (and not just on AnyRef), so you don't need to do any contorsion anymore and can just do any.getClass.
Note though that you still must be prepared to handlet the dual relation between primitive types and their boxed version.
By example getClass on an integer value will return either java.lang.Integer.TYPE (the class of the primitive Int type) or classOf[java.lang.Integer] depending on the static type of the value:
scala> 123.getClass
res1: Class[Int] = int
scala> val x : Int = 123
x: Int = 123
scala> x.getClass
res2: Class[Int] = int
scala> val x: AnyVal = 123
x: AnyVal = 123
scala> x.getClass
res3: Class[_] = class java.lang.Integer
scala> val x: Any = 123
x: Any = 123
scala> x.getClass
res4: Class[_] = class java.lang.Integer
Related
I want to check whether a obj in Scala is of type Array, not caring about whether what type of the values are inside. Is there some easy way to do this?
var x = Array(1,2,3)
x.isInstanceOf[Array[Any]] // which is false
I want it to be true.
Update:
I have a function:
def someFunction(obj: Any) {
if (obj.isInstanceOf[Int]) {
// do something
}
if (obj.isInstanceOf[String]) {
// do something
}
if (obj.isInstanceOf[Array[Any]) {
// for each of the obj inside the Array do something
}
}
array Array(1,2,3) is of type Int, so Array[Any] would weirdly return false only in case of Array collection.
If you don't care the type of Array, you can compare to Array[_] (array of whatever type)
scala> var x = Array(1,2,3)
x: Array[Int] = Array(1, 2, 3)
scala> x.isInstanceOf[Array[Int]]
res0: Boolean = true
scala> x.isInstanceOf[Array[_ <: Any]]
res7: Boolean = true
scala> x.isInstanceOf[Array[_ <: AnyVal]]
res12: Boolean = true
scala> x.isInstanceOf[Array[_]]
res13: Boolean = true
scala.Int extends AnyVal which extends Any you can explicitly mentions _ extends AnyVal.
But other scala collections like List[T] is instance of List[Any]
scala> List(1, 2).isInstanceOf[List[Any]]
res30: Boolean = true
scala> Seq(1, 2).isInstanceOf[Seq[Any]]
res33: Boolean = true
Also, List[T] is instance of Seq[Any], because List extends Seq, and T extends Any
scala> List(1, 2).isInstanceOf[Seq[Any]]
res35: Boolean = true
AND, for if else you can solve with pattern match way,
array match {
case x: Int => println("int")
case x: String => "string"
case Array[Int] => println("ints")
case Array[String] => println("strings")
case _ => println("whatever")
}
x.isInstanceOf[Array[_]]
use _ for container any type match. and for _ it's called existential type.
Document:
Underscore for existential type in Scala
I have a macro that does some analysis on nested function applications. It matches applications and retrieve the parameter types this way:
case q"$f[..$targs](..$args)(...$otherArgs)" =>
// retrieve the list of all parameter types
val paramTpes = f.tpe match {
case pmt: PolyType if pmt.paramLists.size == 0 =>
Seq()
case pmt: PolyType =>
pmt.paramLists(0) map {_.typeSignature
.substituteTypes(pmt.typeParams, targs map (_.tpe))}
case pmt: MethodType if pmt.paramLists.size == 0 =>
Seq()
case pmt: MethodType =>
pmt.paramLists(0) map (_.typeSignature)
}
Now, if there happen to be by-name parameters, what I get is some weird type that prints => T but cannot be matched with anything. There seem to be no facility in the reflection API to handle these properly.
What I would like to do is retrieve T in case it' a => T, because => T causes further problems in the generated code.
Usually, use the extractors. Sometimes I have to see what the runtime class is, to remember what extractor to use. I don't use the API every day.
scala> import reflect.runtime._, universe._
import reflect.runtime._
import universe._
scala> class X { def x(i: => Int) = i * 2 }
defined class X
scala> typeOf[X].member(TermName("x"))
res0: reflect.runtime.universe.Symbol = method x
scala> .typeSignature
res1: reflect.runtime.universe.Type = (i: => scala.Int)scala.Int
scala> res1 match { case MethodType(ps, res) => ps }
res2: List[reflect.runtime.universe.Symbol] = List(value i)
scala> .head
res3: reflect.runtime.universe.Symbol = value i
scala> .typeSignature
res4: reflect.runtime.universe.Type = => scala.Int
scala> res4.getClass
res5: Class[_ <: reflect.runtime.universe.Type] = class scala.reflect.internal.Types$ClassArgsTypeRef
scala> res4 match { case TypeRef(pre, sym, args) => sym }
res6: reflect.runtime.universe.Symbol = class <byname>
scala> res4 match { case TypeRef(pre, sym, args) => args }
res7: List[reflect.runtime.universe.Type] = List(scala.Int)
scala> definitions
res8: reflect.runtime.universe.DefinitionsApi = scala.reflect.internal.Definitions$definitions$#4e80a001
scala> definitions.By
ByNameParamClass ByteClass ByteTpe
scala> definitions.ByNameParamClass
res9: reflect.runtime.universe.ClassSymbol = class <byname>
I vaguely remember the special name, but do I get a stable prefix for pattern matching? I guess not.
scala> res4 match { case TypeRef(pre, definitions.ByNameParamClass, args) => args }
<console>:20: error: stable identifier required, but scala.reflect.runtime.`package`.universe.definitions.ByNameParamClass found.
Note that method ByNameParamClass is not stable because its type, => reflect.runtime.universe.ClassSymbol, is volatile.
res4 match { case TypeRef(pre, definitions.ByNameParamClass, args) => args }
^
scala> val k = definitions.ByNameParamClass
k: reflect.runtime.universe.ClassSymbol = class <byname>
scala> res4 match { case TypeRef(pre, k, args) => args }
res11: List[reflect.runtime.universe.Type] = List(scala.Int)
scala>
I'm trying to test whether a method's return type exactly matches a supplied type.
Somehow, I've found two String Types that are not equal.
class VarAndValue {
#BeanProperty
val value = "";
}
class ScalaReflectionTest {
#Test
def myTest(): Unit = {
val type1 = universe.typeOf[String]
// Get return value of VarAndValue.getValue
val type2 = universe.typeOf[VarAndValue].
declarations.
filter { m => m.name.decoded == "getValue" && m.isMethod }.
head.
asInstanceOf[universe.MethodSymbol].
returnType
println(type1) // String
println(type2) // String
println(type1.getClass())
println(type2.getClass()) // !=type1.getClass() !!
println(type1==type2) // False
}
}
yields...
String
String
class scala.reflect.internal.Types$TypeRef$$anon$3
class scala.reflect.internal.Types$TypeRef$$anon$6
false
How can I filter methods of a class by their return type? (It seems very difficult if I can test for equality of the return types).
Scala 2.10
UPDATE:
I can't drop into the Java reflection universe because this erased type information for generics like List[Int] (which become List[Object] is java-land where they're really List[java.lang.Integer]). I need my matched to pay attention to the generic parameter information that the scala type universe preserves.
Use =:= to compare types.
scala> import beans._
import beans._
scala> :pa
// Entering paste mode (ctrl-D to finish)
class VarAndValue {
#BeanProperty
val value = "";
}
// Exiting paste mode, now interpreting.
defined class VarAndValue
scala> import reflect.runtime._, universe._
import reflect.runtime._
import universe._
scala> val str = typeOf[String]
str: reflect.runtime.universe.Type = String
scala> val ms = typeOf[VarAndValue].declarations filter (m => m.isMethod && m.name.decoded == "getValue")
warning: there were two deprecation warnings; re-run with -deprecation for details
ms: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(method getValue)
scala> val mm = ms.toList
mm: List[reflect.runtime.universe.Symbol] = List(method getValue)
scala> val m = mm.head.asInstanceOf[MethodSymbol]
m: reflect.runtime.universe.MethodSymbol = method getValue
scala> val t = m.returnType
t: reflect.runtime.universe.Type = java.lang.String
scala> println(t)
java.lang.String
scala> println(str)
String
scala> str == t
res2: Boolean = false
scala> str match { case `t` => }
scala.MatchError: String (of class scala.reflect.internal.Types$AliasNoArgsTypeRef)
... 33 elided
scala> str =:= t
res4: Boolean = true
scala> str match { case TypeRef(a,b,c) => (a,b,c) }
res5: (reflect.runtime.universe.Type, reflect.runtime.universe.Symbol, List[reflect.runtime.universe.Type]) = (scala.Predef.type,type String,List())
scala> t match { case TypeRef(a,b,c) => (a,b,c) }
res6: (reflect.runtime.universe.Type, reflect.runtime.universe.Symbol, List[reflect.runtime.universe.Type]) = (java.lang.type,class String,List())
Depending on what you're going for, consider that conforming types can have differing representations:
scala> typeOf[List[Int]]
res11: reflect.runtime.universe.Type = scala.List[Int]
scala> type X = List[Int]
defined type alias X
scala> typeOf[X].dealias
res12: reflect.runtime.universe.Type = List[scala.Int]
scala> res11 =:= res12
res13: Boolean = true
scala> res11 == res12
res14: Boolean = false
scala> typeOf[X] <:< res11
res15: Boolean = true
scala> typeOf[X] =:= res11
res16: Boolean = true
Turns out this is the way to compare types ...
type1 match {
case type2 => true
case _ => false
}
which gives a different answer than type1==type.
Scala is a strange beast.
When I'm matching value of case classes, such as:
sealed abstract class Op
case class UOp[T, K](f: T => K) extends Op
case class BOp[T, Z, K](f: (T, Z) => K) extends Op
like this:
def f(op: Op): Int =
op match
{
case BOp(g) => g(1,2)
case UOp(g) => g(0)
}
the compiler infers it as
val g: (Nothing, Nothing) => Any
val g: Nothing => Any
Why am I getting Nothing as the type? Is it because of JVM type erasure? Are there elegant ways to match functions against variables?
I came up with this "hackish" solution, maybe there are other ways or cleaner ways to do this still without relying on reflection.
Define a few partial functions which will handle various args:
scala> val f: PartialFunction[Any, String] = { case (x: Int, y: String) => y * x }
f: PartialFunction[Any,String] = <function1>
scala> val g: PartialFunction[Any, String] = { case x: Int => x.toString }
g: PartialFunction[Any,String] = <function1>
scala> def h: PartialFunction[Any, BigDecimal] = { case (a: Int, b: Double, c: Long) => BigDecimal(a) + b + c }
h: PartialFunction[Any,BigDecimal]
scala> val l: List[PartialFunction[Any, Any]] = f :: g :: h :: Nil
l: List[PartialFunction[Any,Any]] = List(<function1>, <function1>, <function1>)
Check which functions can handle different inputs:
scala> l.map(_.isDefinedAt(1))
res0: List[Boolean] = List(false, true, false)
scala> l.map(_.isDefinedAt((1, "one")))
res1: List[Boolean] = List(true, false, false)
Given input find and apply a function:
scala> def applyFunction(input: Any): Option[Any] = {
| l find (_.isDefinedAt(input)) map (_ (input))
| }
applyFunction: (input: Any)Option[Any]
scala> applyFunction(1)
res1: Option[Any] = Some(1)
scala> applyFunction((2, "one"))
res2: Option[Any] = Some(oneone)
scala> applyFunction("one")
res3: Option[Any] = None
scala> applyFunction(1, 1.1, 9L)
res10: Option[Any] = Some(11.1)
This looks quite type unsafe and there must be better ways to do this.
I think magnet pattern should handle this well in more typesafe manner.
I have an heterogeneous List like the following one:
val l = List(1, "One", true)
and I need to filter its objects by extracting only the ones belonging to a given Class. For this purpose I wrote a very simple method like this:
def filterByClass[A](l: List[_], c: Class[A]) =
l filter (_.asInstanceOf[AnyRef].getClass() == c)
Note that I am obliged to add the explicit conversion to AnyRef in order to avoid this compilation problem:
error: type mismatch;
found : _$1 where type _$1
required: ?{val getClass(): ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method any2stringadd in object Predef of type (x: Any)scala.runtime.StringAdd
and method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
are possible conversion functions from _$1 to ?{val getClass(): ?}
l filter (_.getClass() == c)
However in this way the invocation of:
filterByClass(l, classOf[String])
returns as expected:
List(One)
but of course the same doesn't work, for example, with Int since they extends Any but not AnyRef, so by invoking:
filterByClass(l, classOf[Int])
the result is just the empty List.
Is there a way to make my filterByClass method working even with Int, Boolean and all the other classes extending Any?
The collect method already does what you want. For example to collect all Ints in a collection you could write
xs collect { case x: Int => x }
This of course only works when you hardcode the type but as primitives are handled differently from reference types it is actually better to do so. You can make your life easier with some type classes:
case class Collect[A](collect: PartialFunction[Any,A])
object Collect {
implicit val collectInt: Collect[Int] = Collect[Int]({case x: Int => x})
// repeat for other primitives
// for types that extend AnyRef
implicit def collectAnyRef[A <: AnyRef](implicit mf: ClassManifest[A]) =
Collect[A]({ case x if mf.erasure.isInstance(x) => x.asInstanceOf[A] })
}
def collectInstance[A : Collect](xs: List[_ >: A]) =
xs.collect(implicitly[Collect[A]].collect)
Then you can use it without even passing a Class[A] instance:
scala> collectInstance[Int](l)
res5: List[Int] = List(1)
scala> collectInstance[String](l)
res6: List[String] = List(One)
Using isInstanceOf:
scala> val l = List(1, "One", 2)
l: List[Any] = List(1, One, 2)
scala> l . filter(_.isInstanceOf[String])
res1: List[Any] = List(One)
scala> l . filter(_.isInstanceOf[Int])
res2: List[Any] = List(1, 2)
edit:
As the OP requested, here's another version that moves the check in a method. I Couldn't find a way to use isInstanceOf and so I changed the implementation to use a ClassManifest:
def filterByClass[A](l: List[_])(implicit mf: ClassManifest[A]) =
l.filter(mf.erasure.isInstance(_))
Some usage scenarios:
scala> filterByClass[String](l)
res5: List[Any] = List(One)
scala> filterByClass[java.lang.Integer](l)
res6: List[Any] = List(1, 2)
scala> filterByClass[Int](l)
res7: List[Any] = List()
As can be seen above, this solution doesn't work with Scala's Int type.
The class of an element in a List[Any] is never classOf[Int], so this is behaving as expected. Your assumptions apparently leave this unexpected, but it's hard to give you a better way because the right way is "don't do that."
What do you think can be said about the classes of the members of a heterogenous list? Maybe this is illustrative. I'm curious how you think java does it better.
scala> def f[T: Manifest](xs: List[T]) = println(manifest[T] + ", " + manifest[T].erasure)
f: [T](xs: List[T])(implicit evidence$1: Manifest[T])Unit
scala> f(List(1))
Int, int
scala> f(List(1, true))
AnyVal, class java.lang.Object
scala> f(List(1, "One", true))
Any, class java.lang.Object
This worked for me. Is this what you want?
scala> val l = List(1, "One", true)
l: List[Any] = List(1, One, true)
scala> l filter { case x: String => true; case _ => false }
res0: List[Any] = List(One)
scala> l filter { case x: Int => true; case _ => false }
res1: List[Any] = List(1)
scala> l filter { case x: Boolean => true; case _ => false }
res2: List[Any] = List(true)
Despite my solution could be less elegant than this one I find mine quicker and easier. I just defined a method like this:
private def normalizeClass(c: Class[_]): Class[_] =
if (classOf[AnyRef].isAssignableFrom((c))) c
else if (c == classOf[Int]) classOf[java.lang.Integer]
// Add all other primitive types
else classOf[java.lang.Boolean]
So by using it in my former filterByClass method as it follows:
def filterByClass[A](l: List[_], c: Class[A]) =
l filter (normalizeClass(c).isInstance(_))
the invocation of:
filterByClass(List(1, "One", false), classOf[Int])
just returns
List(1)
as expected.
At the end, this problem reduces to find a map between a primitive and the corresponding boxed type.
Maybe a help can arrive from scala.reflect.Invocation (not included in the final version of 2.8.0), the getAnyValClass function in particular (here slightly edited)
def getAnyValClass(x: Any): java.lang.Class[_] = x match {
case _: Byte => classOf[Byte]
case _: Short => classOf[Short]
case _: Int => classOf[Int]
case _: Long => classOf[Long]
case _: Float => classOf[Float]
case _: Double => classOf[Double]
case _: Char => classOf[Char]
case _: Boolean => classOf[Boolean]
case _: Unit => classOf[Unit]
case x#_ => x.asInstanceOf[AnyRef].getClass
}
With this function the filter is as easy as
def filterByClass[T: Manifest](l:List[Any]) = {
l filter (getAnyValClass(_) == manifest[T].erasure)
}
and the invocation is:
filterByClass[Int](List(1,"one",true))