Scala Singleton not working as expected - scala

Main.scala:
package controler
object Main {
def main(args: Array[String]) {
import Utilites._
isJavaUpToDate
}
}
Utilites.scala:
package controler
object Utilities {
def isJavaUpToDate = {
val javaVersion = augmentString(System.getProperty("java.version").substring(2, 3))
javaVersion >= 6
}
}
Why isn't this working?
I have been trought a bunch of differenet tutorial sites where this works no problem.
I always says that val Utilites cannot be found.
P.S. Why does it keep sugesting me to change .toInt with augmentString() when it just breaks the code?
Now this gives me trouble, something about implicit ordering and method orderTOOrdered.

In your main method you've typed Utilites where you meant to type Utilities.
Correct: Utilities
Wrong: Utilites
Note the missing i :) And because your brain is a powerful spelling correction tool, it pretended like the spelling was correct. The Scala compiler isn't as cool, though ;)
Also, for me, the following does not work:
scala> augmentString(System.getProperty("java.version").substring(2, 3)) >= 5
<console>:15: error: No implicit Ordering defined for AnyVal.
augmentString(System.getProperty("java.version").substring(2, 3)) >= 5
Instead I replaced it with
System.getProperty("java.version").substring(2, 3)).toInt >= 5
The implicit ordering issue you experienced with the former code is because Scala does not know how to apply the >= method/operator to the type scala.collection.immutable.StringOps, which augmentString() returns.

Note that by calling augmentString you're explicitly transforming your string to a StringOps.
StringOps does define a >= method, but it's meant to compare strings (its signature is def >=(that: String): Boolean )
If you want to compare Ints you should use the toInt method defined in StringOps.
def isJavaUpToDate = {
val javaVersion = augmentString(System.getProperty("java.version").substring(2, 3)).toInt
javaVersion >= 6
}
Also, unless you need to disambiguate the toInt against another implicit that you defined (or is defined somewhere else in a library you're using) there should be no need to call augmentString explicitly. The following should just work (unless the compiler tells you it does not) and it should implicitly have the same effect as the code above of transforming your String to a StringOps.
def isJavaUpToDate = {
val javaVersion = System.getProperty("java.version").substring(2, 3)
javaVersion.toInt >= 6
}
EDIT: as per #som-snytt's comment
The error you're getting (No implicit Ordering defined for AnyVal) is due to the compiler reasoning more or less like this:
javaVersion >= 6 means javaVersion.>=(6), i.e. I must look for a method called >= on javaVersion that takes an integer
javaVersion is a StringOps... there is a >= method in StringOps (courtesy of the StringLike trait it's extending, that in turn extends Ordered[String]) but it takes a String argument, not an Int
let's see if I have an implicit in scope that supplies a suitable Ordering for StringOps. Now, since you're trying to compare a String with a Int you're looking at an Ordering that can compare two values with the nearest common ancestor that can contain both String and Int, i.e. AnyVal [EDIT: although String is an AnyRef so I don't really get this part...].
No luck there... give up with an error that says that no implicit Ordering was found comparing AnyVals

Related

Scala reflection with Int parameter

In the below code, I try to invoke an object's method that has an Int parameter (giving it a value of 3). This returns an error that Int and 3 are incompatible types.
//Using scala's Int does not work!
object MyObject{
def handleInt(id:Int) : Boolean = {
true
}
}
object testApp extends App {
val obj = MyObject.getClass
val method = obj.getDeclaredMethod("handleInt", classOf[Int]) //Int.getClass shows the same behavior
val rsp = method.invoke(obj, 3)
}
Error:(106, 41) the result type of an implicit conversion must be more
specific than AnyRef
val rsp = method.invoke(obj, 3)
Error:(106, 41) type mismatch; found : Int(3) required: Object
val rsp = method.invoke(obj, 3)
I tried modifying a lot of things here, the only way this could work is by changing all signatures to Java's Integer. The code will look like this:
//This works with Java's Integer
object MyObject{
def handleInt(id:Integer) : Boolean = {
true
}
}
object testApp extends App {
val obj = MyObject.getClass
val method = obj.getDeclaredMethod("handleInt", classOf[Integer])
val rsp = method.invoke(obj, 3)
}
My question(s) are:
Can someone explain why this happens? I think scala's Int wraps java's primitive int (which is why this is not considered an object), but I'm not sure.
Is there a way to achieve this using Scala's Int type?
Is it acceptable to mix scala and java types like this? Is it a good practice?
The first problem is that you invoke method on the wrong object: obj doesn't have handleInt method, MyObject does. The second is kind of an edge case: invoke takes Object... varargs and Scala doesn't automatically convert an Int directly to Object because that's not what you normally want to do. You can use a type ascription to say "box this Int into an Integer" and then Scala will upcast it to Object automatically.
So, combining these 2 fixes: you don't need to change handleInt or val method, just
val rsp = method.invoke(MyObject, 3: Integer)
To answer your final question: use of Integer, java.lang.Double, etc. shouldn't be common in Scala code, but it isn't particularly problematic. And reflection is one of the areas where you may have to use them.
No we cannot use Scala types.
Its Ok to mix Java and Scala types.
As reflection deals with reading class bytecode at Runtime. At bytecode level only types that are visible are the Java types because all scala types are boiled down to Java types.

Possible to find parameter type methods return type in Scala where parameter is a primitive type?

Suppose I have:
class X
{
val listPrimitive: List[Int] = null
val listX: List[X] = null
}
and I print out the return types of each method in Scala as follows:
classOf[ComplexType].getMethods().foreach { m => println(s"${m.getName}: ${m.getGenericReturnType()}") }
listPrimitive: scala.collection.immutable.List<Object>
listX: scala.collection.immutable.List<X>
So... I can determine that the listX's element type is X, but is there any way to determine via reflection that listPrimitive's element type is actually java.lang.Integer? ...
val list:List[Int] = List[Int](123);
val listErased:List[_] = list;
println(s"${listErased(0).getClass()}") // java.lang.Integer
NB. This seems not to be an issue due to JVM type erasure since I can find the types parameter of List. It looks like the scala compiler throws away this type information IFF the parameter type is java.lang.[numbers] .
UPDATE:
I suspect this type information is available, due to the following experiment. Suppose I define:
class TestX{
def f(x:X):Unit = {
val floats:List[Float] = x.listPrimitive() // type mismatch error
}
}
and X.class is imported via a jar. The full type information must be available in X.class in order that this case correctly fails to compile.
UPDATE2:
Imagine you're writing a scala extension to a Java serialization library. You need to implement a:
def getSerializer(clz:Class[_]):Serializer
function that needs to do different things depending on whether:
clz==List[Int] (or equivalently: List[java.lang.Integer])
clz==List[Float] (or equivalently: List[java.lang.Float])
clz==List[MyClass]
My problem is that I will only ever see:
clz==List[Object]
clz==List[Object]
clz==List[MyClass]
because clz is provided to this function as clz.getMethods()(i).getGenericReturnType().
Starting with clz:Class[_] how can I recover the element type information that was lost?
Its not clear to me that TypeToken will help me because its usages:
typeTag[T]
requires that I provide T (ie. at compile time).
So, one path to a solution... Given some clz:Class[_], can I determine the TypeTokens of its method's return types? Clearly this is possible as this information must be contained (somewhere) in a .class file for a scala compiler to correctly generate type mismatch errors (see above).
At the java bytecode level Ints have to be represented as something else (apparently Object) because a List can only contain objects, not primitives. So that's what java-level reflection can tell you. But the scala type information is, as you infer, present (at the bytecode level it's in an annotation, IIRC), so you should be able to inspect it with scala reflection:
import scala.reflect.runtime.universe._
val list:List[Int] = List[Int](123)
def printTypeOf[A: TypeTag](a: A) = println(typeOf[A])
printTypeOf(list)
Response to update2: you should use scala reflection to obtain a mirror, not the Class[_] object. You can go via the class name if need be:
import scala.reflect.runtime.universe._
val rm = runtimeMirror(getClass.getClassLoader)
val someClass: Class[_] = ...
val scalaMirrorOfClass = rm.staticClass(someClass.getName)
// or possibly rm.reflectClass(someClass) ?
val someObject: Any = ...
val scalaMirrorOfObject = rm.reflectClass(someObject)
I guess if you really only have the class, you could create a classloader that only loads that class? I can't imagine a use case where you wouldn't have the class, or even a value, though.

Reify a ValDef from compile to runtime

I want to reify a ValDef into runtime, but i does not work directly. If i encapsulate the ValDef into a Block, everything works perfectly, like in the following example:
case class Container(expr: Expr[Any])
def lift(expr: Any): Container = macro reifyValDef
def reifyValDef(c: Context)(expr: c.Expr[Any]): c.Expr[Container] = {
import c.universe._
expr.tree match {
case Block(List(v: ValDef), _) =>
val asBlock = q"{$v}"
val toRuntime = q"scala.reflect.runtime.universe.reify($asBlock)"
c.Expr[Container](q"Container($toRuntime)")
}
}
lift {
val x: Int = 10
}
If i would use v directly, instead of wrapping it into a block, I get the error:
Error:(10, 11) type mismatch;
found :
required: Any
Note that extends Any, not AnyRef.
Such types can participate in value classes, but instances
cannot appear in singleton types or in reference comparisons.
val x: Int = 10
^
Is it just not working directly with ValDefs or is something wrong with my code?
That's one of the known issues in the reflection API. Definitions are technically not expressions, so you can't e.g. pass them directly as arguments to functions. Wrapping the definition in a block is a correct way of addressing the block.
The error message is of course confusing, but it does make some twisted sense. To signify the fact that a definition by itself doesn't have a type, the tpe field of the corresponding Tree is set to NoType. Then the type of the argument of a macro is checked against Any and the check fails (because NoType is a special type, which isn't compatible with anything), so a standard error message is printed. The awkward printout is an artifact of how the prettyprinter behaves in this weird situation.

Scala multiple implicit conversions?

I don't understand the apparent contradictory behavior I'm seeing in the following code (Scala 2.9):
class Pimp1(val x : Double) {
def pluss(that : Pimp1) = x + that.x
def <(that : Pimp1) = x < that.x
}
object Pimp1 {
implicit def d2pimp(d : Double) = new Pimp1(d)
implicit def d2pimp(od : Option[Double]) = new Pimp1(od.get)
}
object Scratch2 extends App {
import Pimp1._
5.0.pluss(Some(5.0))
5.0 < Some(5.0)
}
The line '5.0.pluss(Some(5.0))' compiles, but the line after it does not compile with the following error message:
overloaded method value < with alternatives: (x: Double)Boolean (x: Float)Boolean (x: Long)Boolean (x: Int)Boolean (x: Char)Boolean (x: Short)Boolean (x: Byte)Boolean cannot be applied to (Some[Double])
If I add explicit < operator to the Pimp class that takes an Option[Double]:
def <(that : Option[Double]) = x < that.get
Everything compiles fine.
Now, the way I understand Scala implicit conversion rules, this makes perfect sense:
The compiler understands that there's no '<' operator on Double that accepts Option[Double]
It considers the implicit conversion to Pimp1.
If Pimp1 has a suitable operator, it works, otherwise, it generates an error.
Importantly, this demonstrates that the compiler does not consider applying a second (available) implicit conversion, from Option[Double] to Pimp.
This is how I expected things to work.
However, this seems to be contradicted by the first example, where:
The compiler sees that there's no pluss method on Double.
The compiler tries the implicit conversion to Pimp, which does have such a method.
However, in order to make the operator work, the compiler has to apply a second implicit conversion, on the argument, to convert it to Pimp.
According to the logic above, this should not compile, but it does. Do the implicit conversion rules treat non-existing methods and non-matching methods differently?
This makes sense to me. The first one, that works goes like this:
Does Double have a pluss method? No, can we implicitly convert it to something that does? Yes. Ok, now I want to apply the pluss method. Does it take an Option? No. Can I implictly convert Option to soemthing that it does take? yes.
The second one goes like this:
Does Double have a < method? Yes. Does it take an Option? No. can I implicitly convert Option to something that < does take? No.

List of String implicit conversions like +=

Consider the following snippet. += is not a member of java.lang.String, so I guess there is some sort of Implicit conversion going on. How do I find a list of such predefined implicit conversions acting on String?
scala> var x = "asdf"
x: java.lang.String = asdf
scala> x += x
scala> x
res2: java.lang.String = asdfasdf
You picked a particularly bad example. += is, in a sense, part of String. See this comment on the Javadoc for java.lang.String:
The Java language provides special support for the string
concatenation operator ( + ), and for conversion of other objects to
strings.
You'll have to look up Java language specification to find more information about it (15.18.1). But, then again, Scala is not Java, so + is also part of the Scala language specification (12.3.1).
So far I have spoken of +, not +=. However, Scala has a special syntactic sugar for assignment. As described in section 6.12.4, except for <=, >=, != and operators starting with an =, any operator symbol (see "operator characters" in chapter 1) that ends in an equal sign will be reinterpreted if it does not exist as a method. Specifically,
x += 1
will be reinterpreted as
x = x + 1
That will happen regardless of whether x is a var, so one might occasionally see an error message "reassignment to val".
So, as you can see, += is really part of String, through an exception in Java specification that was replicated in Scala specification, plus a bit of syntactic sugar.
Which doesn't mean there aren't methods not in java.lang.String that can be used with it through implicit conversions. I'll leave that to the other answers, however. If I were you, I'd change the method in the question, to make it correct. Besides, += is unsearchable in Stack Overflow.
You need to look in scala.Predef - all implicits that are defined there would be always in scope (so you don't need to import them).
If you look in it's source code, you will find this section:
// Strings and CharSequences ------------
...
implicit def augmentString(x: String): StringOps = new StringOps(x)
implicit def unaugmentString(x: StringOps): String = x.repr
...
StringOps defines implicit conversions for String. It gets imported into the scope in scala.Predef along with other useful things.
Not specific to String, but the Scala REPL has a neat feature to see all the implicits in scope:
scala> :implicits
No implicits have been imported other than those in Predef.
scala> :implicits -v
/* 96 implicit members imported from scala.Predef */
/* 66 inherited from scala.Predef */
implicit def Double2double(x: jl.Double): Double
implicit def byte2double(x: Byte): Double
implicit def char2double(x: Char): Double
...
/* 30 inherited from scala.LowPriorityImplicits */
implicit def genericWrapArray[T](xs: Array[T]): mutable.WrappedArray[T]
implicit def wrapBooleanArray(xs: Array[Boolean]): mutable.WrappedArray[Boolean]
implicit def wrapByteArray(xs: Array[Byte]): mutable.WrappedArray[Byte]
...
It's also worth noting that implicits don't have to be in scope to be applied. For example, we can define an implicit conversion in a companion object,
case class Foo(s: String)
object Foo { implicit def string2Foo(s: String) = Foo(s.reverse) }
and then apply it, even though its not in scope,
scala> val f: Foo = "hello"
f: Foo = Foo(olleh)
The Foo companion object is searched for implicits because the target type is Foo. For more info, see Daniel Sobral's answer to: Where does Scala look for implicits?