How does Scala java conversion work? - scala

If I have java.util.List and want to iterate over it user Scala syntax I import :
import scala.collection.JavaConversions._
and the java.util.List is implicitly converted to scala.collection.mutable.Set
(http://www.scala-lang.org/api/current/index.html#scala.collection.JavaConversions%24)
But how is this conversion achieved ? I'm confused as this is the first time I've encountered the ability to convert an object type by just importing a package.

JavaConversions object contains many implicit conversions between Scala->Java and Java->Scala collections. When you import all members of JavaConversions, all of those conversions are put in the current scope, and are therefore evaluated when an immediate collection type isn't available.
For example, when Scala compiler is looking for a collection of type X and cannot find it, it will also try to find a collection of type Y and an implicit conversion Y to X in scope.
To understand more about how the conversions are evaluated, see this answer.

There is a pattern "Pimp my library" that allows to "add" methods to any existing class. See for instance the answer of Daniel C. Sobral, http://www.artima.com/weblogs/viewpost.jsp?thread=179766, or google other examples.
In short: an implicit method returns a wrapper with the desired methods:
implicit def enrichString(s:String) = new EnrichedString(s)
class EnrichedString(s:String){
def hello = "Hello, "+s
}
assert("World".hello === "Hello, World")
It can also be shortened with sugar:
implicit class EnrichedString(s:String){
def hello = "Hello, "+s
}

Related

scala : library is looking for an implicit value to be declared

I am using two imports
import org.json4s._
import org.json4s.native.JsonMethods._
I have the following source code
val json = parse("~~~~~~aklsdjfalksdjfalkdsf")
var abc = (json \\ "something").children map {
_.extract[POJO]
}
After I ran it I saw
Error:(32, 18) No org.json4s.Formats found. Try to bring an instance of org.json4s.Formats in scope or use the org.json4s.DefaultFormats.
_.extract[POJO]
Error:(32, 18) not enough arguments for method extract: (implicit formats: org.json4s.Formats, implicit mf: scala.reflect.Manifest[POJO])POJO.
Unspecified value parameters formats, mf.
_.extract[POJO]
I know I should be declaring :
implicit val df = DefaultFormats
I learnt how to use 'implicit' for my scala code.
However I need to understand how to use a library that enforces developers to define an implicit variable in their source code.
It seems a keyword 'implicit' is used in 'extract' method in ExtractableJsonAstNode class file as stated in the error message.
def extract[A](implicit formats: Formats, mf: scala.reflect.Manifest[A]): A =
Extraction.extract(jv)(formats, mf)
I see that that is looking for 'implicit' variable keyword to be declard in my source code.
The first question is how do I know when an implicit keyword is to be used for another implicit keyword (e.g. declared in a library), or it's going to be a switch of an operation I define (case that 'implicit' not to be declared twice)
the only clue I have is, when mother source code is using 'implicit' keyword and using a variable and it's type is a trait. Then I(dev) need to declare a variable with a type of a concrete class that extends that trait. I don't know if it's true..
also I found the following source code in 'Formats.scala' file within the json library.
class CustomSerializer[A: Manifest](
ser: Formats => (PartialFunction[JValue, A], PartialFunction[Any, JValue])) extends Serializer[A] {
val Class = implicitly[Manifest[A]].runtimeClass
def deserialize(implicit format: Formats) = {
case (TypeInfo(Class, _), json) =>
if (ser(format)._1.isDefinedAt(json)) ser(format)._1(json)
else throw new MappingException("Can't convert " + json + " to " + Class)
}
def serialize(implicit format: Formats) = ser(format)._2
}
note that def deserialize(implicit format: Formats) is declared.
once I write 'implicit val df = DefaultFormats' in my file, will it affect the whole json mechanism not only the 'extract' method? as CustomSerializer is used in json library.
to summarise..
the first question is about one of 'implicit' keyword usages.
the second question is about 'implicit' keyword scope.
When do I use the implicit keyword?
Implicits are used to defne the behavior of things you normally do not have control over. In your question, DefaultFormats is already an implicit. You do not need to declare a new implicit using it, you can just import it.
As for knowing when a library you're using requires some implicit in scope, that error is it. It is essentially telling you "if you're not sure what this error is about you can just import DefaultFormats.
Will an implicit affect the whole mechanism?
This is a key question that is important to understand.
When you have a function that takes an implicit, your compiler will search the scope for an implicit of that type.
Your function is looking for org.json4s.Formats. By importing DefaultFormat or writing your own implicit of type Format, you are teliing your function to use that format.
What effect does this have on the rest of your code?
Any other functions you have that rely on an implicit Format in the scope will use the same implicit. This is probably fine for you.
If you need to use multiple different Formats, you will want to split up those components from each other. You do not want to define multiple implicits of the same type in the same scope. This is confusing for humans and computers and should just be avoided.

How to get a Scala runtime class with generic parameters?

I wonder if it is possible to do something like the following:
import scala.reflect.runtime.universe._
class Bar[T]
def foo[T]()(implicit ctag: reflect.ClassTag[T]) {
val clazz = classOf[Bar[ctag.runtimeClass.asInstanceOf[Class[T]]]]
}
Here the Scala compiler complains:
error: stable identifier required, but ctag.runtimeClass found.
Is there a way to get the class type with type parameters inserted from the runtime type information available in the function?
Is there a way to get the class type with type parameters inserted from the runtime type information available in the function?
classOf[Bar[T]] works for a very simple reason: it doesn't insert any runtime information! classOf[Bar[T]], classOf[Bar[String]], classOf[Bar[Int]], classOf[Bar[_]] are all the same; that's what type erasure means in JVM context (to avoid misleading, I prefer always using classOf[Bar[_]] where possible). Note that there is actually a single exception: if Bar is Array, because classOf[Array[Int]] and classOf[Array[Object]] (e.g.) are different!
classOf[T] obviously would need runtime information and so it doesn't work.
Thanks to the comment by #Mr. V I realized that its actually easier than I initially thought:
import scala.reflect.runtime.universe._
class Bar[T]
def foo[T]() {
val clazz = classOf[Bar[T]]
}

Can I use a class defined in a `ToolBox` as a type parameter of `typeOf[]`?

I'd like to experiment with the use of a dynamic data model with a reflective library that uses typeOf[].
I've defined a class at runtime with a Scala reflection ToolBox in 2.11:
import scala.tools.reflect.ToolBox
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{ currentMirror => cm }
def cdef() = q"case class C(v: String)"
val tb = cm.mkToolBox()
val csym = tb.define(cdef())
def newc(csym: Symbol) = q"""new ${csym}("hi")"""
val obj = tb.eval(newc(csym))
I'm able to circumvent the typeOf[] call by entering Scala reflection via the ClassSymbol instead, but that requires modifying a library over which I have no immediate control.
Is there any way that I can use it as a type parameter in a library whose entry point is typeOf[]?
I've tried:
The only way I found to go from a value to something that I could use in the type position was use Java reflection to invoke the companion class' apply method and call .type on the result:
val method_apply = obj.getClass.getMethod("apply", "".getClass)
val typeTemplate = method_apply.invoke(obj, "hello")
type MyType = typeTemplate.type
(Keeping with the naming scheme of #xeno_by and #travisbrown 's menagerie of odd types, I might call this "Frankenstein's Type", because it is made from parts, given life at the wrong time, not quite a substitute for the original, and given that this is all happening at runtime, should probably be burned with fire.)
This type alias works as a type parameter is some cases. But in the case of typeOf[MyType], the the compiler makes a TypeTag before the runtime type is defined, so typeOf[MyType] returns a type member that doesn't correspond to the runtime type/class (e.g. TypeTag[package.Example.MyType] instead of TypeTag[package.C])
Should I expect the ToolBox to have generated a TypeTag, and if so, how do I use it?
If I have to make a TypeTag at runtime, this question shows me how, but then how do I attach it to whatever I use as a type parameter?
Thanks for any ideas,
-Julian

Why do we have to explicitly import implicit conversions having implicit parameters from companion objects? Strange.

Let's consider this code:
class A
object A{
implicit def A2Int(implicit a:A)=1
implicit def A2String(a:A)="Hello"
}
object Run extends App{
implicit val a: A =new A
import A.A2Int
// without this import this code does not compile, why ?
// why is no import needed for A2String then ?
def iWantInt(implicit i:Int)=println(i)
def iWantString(implicit s:String)=println(s)
iWantInt
iWantString(a)
}
It runs and prints:
1
Hello
Now, if we comment out the line
import A.A2Int
then we get a compilation error:
With the line commented out, why Scala cannot find A.A2String if it can find A.A2Int ?
How can this problem be fixed ?
Thanks for reading.
The difference is that when you do iWantString(a), the compiler gets some starting point to work from: you are explicitly passing a, which the compiler knows is of type A.
Given that iWantString takes a String and not an A, the compiler will search for an implicit conversion from A to String in order to insert it and make the call succeed.
Implicit lookup rules state that the compiler must look (among other places) in the companion object of class A because type A is the source type of the conversion.
This is where it finds the implicit conversion A2String.
What you must get from this is that it is only because you passed an instance of A that the compiler knew to look for implicit conversions into the companion object of A.
When you just do iWantInt, the compiler has no reason to look into A, so it won't find your method A2Int (and as no other method/value in scope provides an implicit value of type Int, compilation then fails).
For more information about implicit lookup rules, see the
See the scala specification at http://www.scala-lang.org/docu/files/ScalaReference.pdf (chapter 7.2). Here's the most relevant excerpt:
The implicit scope of a type T consists of all companion modules (§5.4) of classes
that are associated with the implicit parameter’s type.

convert unparameterized Java 1.4 Collection to parameterized Scala Sequence

How can I convert a java 1.4 Collection to a Scala Seq?
I am trying to pass a java-collection to a scala method:
import scala.collection.JavaConversions._
// list is a 1.4 java.util.ArrayList
// repository.getDir is Java legacy code
val list = repository.getDir(...)
perform(list)
def perform(entries: List[SVNDirEntry]) = ...
I always receive this error:
type mismatch; found : java.util.Collection[?0] where type ?0 required: List
[SVNDirEntry]
So I guess I have to create the parameterized Sequence myself as Scala is only able to create an unparameterized Iterable?
First you have to make sure that list has the type java.util.List[SVNDirEntry]. To do this, use a cast:
list.asInstanceOf[java.util.List[SVNDirEntry]]
After that, the implicit conversion will be resolved for you if you import the JavaConversions object. An implicit conversion to a Scala sequence exists in the JavaConversions object. See the following example with a list of strings being passed to a method that expects a Scala sequence:
scala> val jvlist: java.util.List[_] = new java.util.ArrayList[String]
jvlist: java.util.List[_] = []
scala> jvlist.asInstanceOf[java.util.List[String]]
res0: java.util.List[String] = []
scala> import collection.JavaConversions._
import collection.JavaConversions._
scala> def perform(scalaseq: Seq[String]) = println("ok")
perform: (scalaseq: scala.collection.Seq[String])Unit
scala> perform(res0)
ok
These conversions do not copy the elements - they simply construct a wrapper around a Java collection. Both versions point to the same underlying data. Thus, there is no implicit conversion in JavaConversions to immutable Scala lists from mutable Java lists, because that would enable changing the contents of a Scala collection that is guaranteed to be immutable.
In short - prefer Seq[...] to List[...] when defining parameters for methods if you can live with a less specific interface (as in perform above). Or write your own function that does the conversion by copying the elements.
You have to cast the legacy collection down to the target type. Something along the lines of:
perform(list.asInstanceOf[List[SVNDirEntry]])