Scala reflection behaves differently on interpreter and compiled code - scala

I have
trait T
class C extends T
compiled to .class files. And the piece of code below to load them:
val loader = ScalaClassLoader fromURLs (/* List[URL] */)
val classB = loader.tryToInitializeClass("B") getOrElse (/* throw something */)
println(classB.asInstanceOf[Class[_]].getInterfaces)
When I run the loading code in Scala interpreter, the result is
res1: Array[java.lang.Class[_]] = Array(interface T, interface scala.ScalaObject)
but when the loading code compiled into .class files and run I got
[Ljava.lang.Class;#1b8e059
Please tell me how to have the compiled loading code yield the result as fine as on the interpreter.

Are you sure you executed the println in the interpreted session? Because the first result you write looks suspiciously like the interpreter displaying the result of just
classB.asInstanceOf[Class[_]].getInterfaces), without the println (res1 is very telling)
On the other hand, the cryptic [Ljava.lang.Class;#1b8e059 is the toString of an Array. So your problem is just that, toString. If you do something like println(yourResult.mkString(", ")), that should be much better. In the REPL, results displays are better than plain toString

Array(interface T, interface scala.ScalaObject) and [Ljava.lang.Class;#1b8e059 are the same type of object, just printed out in different ways.
Array[Class[_]] gets printed out like [Ljava.lang.Class;#1b8e059 when you call the toString on it.
Try the following:
scala> val f = Array[Class[_]](classOf[Map[String, String]], classOf[Object])
f: Array[java.lang.Class[_]] = Array(interface scala.collection.immutable.Map, class java.lang.Object)
scala> f.toString
res1: java.lang.String = [Ljava.lang.Class;#407e62
The REPL is being helpful when it prints out the value of an expression. If you want to print out a useful string in your compiled code, for example:
scala> f.toList.toString
res4: String = List(interface scala.collection.immutable.Map, class java.lang.Object)

The line
res1: Array[java.lang.Class[_]] = Array(interface T, interface scala.ScalaObject)
does not come from your println expression, it comes from the REPL. If an entered expression returns anything except Unit. The REPL prints the name, type and result of the toString method of that object.
name: Type = from toString

Related

Scala compiler generates wrong method signature for Tuple[Int, _]

Scala compiler behaves weirdly with boxing/unboxing in tuples as parameters.
Consider the code:
scala> class Test { def test(p: (Int, String)) = println(p) }
defined class Test
scala> classOf[Test].getMethods()(0)
res2: java.lang.reflect.Method = public void Test.test(scala.Tuple2)
scala> classOf[Test].getMethods()(0).getGenericParameterTypes
res3: Array[java.lang.reflect.Type] = Array(scala.Tuple2<java.lang.Object, java.lang.String>)
scala> // WTF?????? ^^^^^^^^^^^^^^^^
Thus, I'm getting Object instead of Integer. I assume this is somehow related to tuple parameter being #specialized, but cannot wrap my head around how to avoid/fix this.
The problem it causes - it is impossible to reconstruct method parameter via reflection on method signature (e.g. while parsing json).
Even if there's a way to get the right type with scala-reflect it doesn't help much, cause there are a lot of Java libraries around (like Jersey) that use just Java reflection.
UPD:
OK, putting an Integer (instead of Int) into Tuple works ok. But why isn't it done automatically?

Which Object is the consumer for Scala REPL methods?

As I read in some good Scala books the method declared in Scala REPL are not function(They are not values). They are method.So I want to know exactly which object is consumer that method call.
eg when I call println it is syntatic sugar of Predef.println which under the hood call Console.println . So when I define
def sayHello = "Hello"
then on which object it is being called ,means obj.sayHello what obj is ?
Thanks
It looks like REPL does the following if you execute a line:
It wraps it into an anonymous object literal, imports the members of all previously generated objects and compiles that. If the line has a return value, it includes a member resX to that object and stores the return value there.
You can see that by executing stuff like this.
scala> def foo = "asd"; this
foo: String
res0: type = #ee7d9f1
scala> res0.foo
res1: String = asd
scala> def foo = this; this
foo: type
res2: type = #6d86b085
scala> res2.foo
res3: type = #6d86b085
scala> res3.foo.res2.foo.foo.res2
res4: type = #6d86b085
The interesting thing is the type of these objects, its "type", and the class of the objects has an empty name. This does not usually happen, maybe it is, what the compiler API generates, if you just give it a line of code that is not wrapped in any context, something, you normally cannot do in Scala.
If you really want to know it exactly, you probably have to look into the source of Scala. But to use REPL it should be enough to know, that your code is wrapped in a fresh anonymous object each time.

Scala Macros: Convert/parse a Tree to a Name

This is a simplified example but the problem remains the same.
I want to achieve this using macros (scala based pseudocode):
(a: Int) => {
val z = "toShort"
a.z
}
If I reify it, I would obtain something similar to this:
Function(
List(
ValDef(
Modifiers(Flag.PARAM),
newTermName("a"),
Ident(scala.Int),
EmptyTree
)
),
Block(
List(
ValDef(
Modifiers(),
newTermName("z"),
TypeTree(),
Literal(Constant("toShort"))
)
),
Apply(
Select(
Ident(newTermName("a")),
newTermName("toShort")
),
List()
)
)
)
I dont know how to access to a value and then use it as a TermName.
I tried replacing newTermName("toShort") with newTermName(c.Expr[String](Select(Ident(newTermName("z")))).splice) but the compiler doesn't seem to like:
exception during macro expansion:
java.lang.UnsupportedOperationException: the function you're calling has not been spliced by > the compiler.
this means there is a cross-stage evaluation involved, and it needs to be invoked explicitly.
if you're sure this is not an oversight, add scala-compiler.jar to the classpath,
import scala.tools.reflect.Eval and call <your expr>.eval instead.
I've also tried 'eval' as suggested by compiler: newTermName(c.eval(c.Expr[String](...)) but neither worked.
How could I convert a tree like Select(Ident(newTermName("z"))) (which is a access to a value of a local val) to a Name a string which can be used as a parameter for newTermName? Is it possible?
UPDATE:
Here the real problem brought to you as a gist!
Thanks in advance,
I have a hard time understanding what you're trying to achieve, and why you are using Trees everywhere. Trees are really low level, hard to use, tricky, and it is very difficult to understand what the code does. Quasiquotes (http://docs.scala-lang.org/overviews/macros/quasiquotes.html) are the way to go indeed and you can use them on scala 2.10.x production release thanks to the macro paradise plugin (http://docs.scala-lang.org/overviews/macros/paradise.html). The you can simply write q"(a: Int) => {val z = "toShort"; a.z}" and you directly get the tree expression you just typed.
To answer your question, the first point is to remember that macros are evaluated at compile time. They therefore can not generate code which depends on a runtime value. This is why the compiler is complaining about your splice. But if you pass a value which can be computed at compile time, typically a literal, then you can use eval to get its value within your macro code. Eval does suffer a bug though, as indicated in scaladoc. It should only be called on untyped trees. So the way to call eval on an s: c.Expr[String] expression would be val s2 = c.eval(c.Expr[String](c.resetAllAttrs(c.tree.duplicate))) which gives you a String you can then use normally in your code, for instance q"(a: Int) => a.${newTermName(s2)}".
To put it all together, let's imagine you to create a macro that'll output a string value from an object and one of its String field. It'll give something like
def attr[A](a: A, field: String): String = macro attrImpl[A]
def attrImpl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A], field: c.Expr[String]) = {
import c.universe._
val s = c.eval(c.Expr[String](c.resetAllAttrs(field.tree.duplicate)))
c.Expr[String](q"a.${newTermName(s)}")
}
REPL session test:
scala> object a { val field1 = "field1"; val field2 = "field2" }
defined module a
scala> attr(a, "field1")
res0: String = field1
scala> attr(a, "field2")
res1: String = field2
To understand the difference between compile time and runtime, you can meditate about the following result in REPL ;-)
scala> val s = "field1"; attr(a, s)
error: exception during macro expansion:
scala.tools.reflect.ToolBoxError: reflective compilation has failed:
$iw is not an enclosing class
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.throwIfErrors(ToolBoxFactory.scala:311)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.compile(ToolBoxFactory.scala:244)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.compile(ToolBoxFactory.scala:408)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.eval(ToolBoxFactory.scala:411)
at scala.reflect.macros.runtime.Evals$class.eval(Evals.scala:16)
at scala.reflect.macros.runtime.Context.eval(Context.scala:6)
at .attrImpl(<console>:14)
scala> val s = "field1"
s: String = field1
scala> attr(a, s)
res3: String = field1
Hope it helps ;))

Is there a way to print out an object from a script as it would appear in the REPL? (e.g. myList: List[String] = List(Hello there, World!)

I'm coming from a long time Python background. I've always leaned heavily on the type function in Python to spit out what kind of object I'm working with.
e.g.
In[0]: print type("Hello")
Out[0]: >>> string
In[0]: print type(1234)
Out[0]: >>> int
As I make my way into Scala territory, there are times when I'm not entirely sure what kind of object I've ended up with. being able to lay down a quick print type(obj) whenever I get a little lost would be a huge help.
e.g.
println(type(myObj)) /* Whatever the scala equivalent would be */
>>> myObj: List[String] = List(Hello there, World!)
The Scala equivalent of this would be the getClass method (from Java) on java.lang.Object.
For instance:
scala> 1.getClass
res0: Class[Int] = int
scala> Nil.getClass
res1: Class[_ <: scala.collection.immutable.Nil.type] = class scala.collection.immutable.Nil$
scala> "hello".getClass
res2: Class[_ <: String] = class java.lang.String
You can easily access high-fidelity type information using reflection as of Scala 2.10.
Make sure to add the scala-reflect JAR to your classpath beforehand.
A little helper method is useful here:
import scala.reflect.runtime.universe._
def showTypeOf[T: TypeTag](obj: T) {
println(typeOf[T])
}
Usage:
showTypeOf(List(1, 2, 3)) // prints List[Int]

var_dump() in Scala

Is there any convenient way to dump all members of a specified object in Scala,
like var_dump(), PHP function?
As mentioned in "How to Dump/Inspect Object or Variable in Java" (yes, I know, the question is about Scala):
Scala (console) has a very useful feature to inspect or dump variables / object values :
scala> def b = Map("name" -> "Yudha", "age" -> 27)
b: scala.collection.immutable.Map[java.lang.String,Any]
scala> b
res1: scala.collection.immutable.Map[java.lang.String,Any] = Map((name,Yudha), (age,27))
But if you want more details, you can give REPL Scala Utils a try, in order to get a "Easier object inspection in the Scala REPL"
So I've written a utility for use on the Scala REPL that will print out all of the "attributes" of an object.
(Note: "I" being here: Erik Engbrecht, also on BitBucket)
Here's some sample usage:
scala> import replutils._
import replutils._
scala> case class Test(a: CharSequence, b: Int)
defined class Test
scala> val t = Test("hello", 1)
t: Test = Test(hello,1)
scala> printAttrValues(t)
hashCode: int = -229308731
b: int = 1
a: CharSequence (String) = hello
productArity: int = 2
getClass: Class = class line0$object$$iw$$iw$Test
That looks fairly anti-climatic, but after spending hours typing objName to see what's there, and poking at methods, it seems like a miracle.
Also, one neat feature of it is that if the class of the object returned is different from the class declared on the method, it prints both the declared class and the actual returned class.
You might want to look at ToStringBuilder in commons-lang, specificly ToStringBuilder.reflectionToString().
In compiled code, the nicest way is usually just to declare your type as a case class, then use the generated toString method.
Anything else subclassing Product should be just as easy (currently just tuples)
Failing that, write your own toString method, it's usually trivial enough...