I am trying to find the overloaded method using Scala reflections. Here's my code
import scala.reflect.runtime.universe._
object Example {
class Something {
def printIt(s1: String,s2: String) {println(s1 + s2) }
def printIt(s: Int) { println(s) }
def printIt(s: String) {println(s) }
def printInt(i: Int) { println(i) }
def printInt(i: String) { println(i) }
}
def main(args: Array[String]): Unit = {
val r = new Something()
val mirror = runtimeMirror(getClass.getClassLoader)
val instanceMirror = mirror.reflect(r)
val symbols = mirror.typeOf[r.type].decl(TermName("printInt")).asMethod
}
}
When I execute the code I am getting the following exception.
Exception in thread "main" scala.ScalaReflectionException: value printInt encapsulates multiple overloaded alternatives and cannot be treated as a method. Consider invoking `<offending symbol>.asTerm.alternatives` and manually picking the required method
By following the suggestion given by the exception itself, I am able to find the overloaded method by iterating through method alternatives. But is there any way of finding the method using the argument types that the method takes?
Either using Scala reflection and iterating
val m: scala.reflect.runtime.universe.MethodSymbol =
typeOf[Something].decl(TermName("printInt")).asTerm.alternatives.find(s =>
s.asMethod.paramLists.map(_.map(_.typeSignature)) == List(List(typeOf[Int]))
).get.asMethod
or using Java reflection
val m: java.lang.reflect.Method =
Class.forName("Example$Something").getMethod("printInt", classOf[Int])
Related
Usually the "memeber" in trait is defined as def variable:Type, then other memebers which depend on variable uses lazy val to prevent variable being null when getting initialized.
However if it is a piece of logic, e.g. a function call depends on variable will still throw null exception. Like the code below:
trait A {
def variable:Seq[String]
if (variable.size > 3) // check
println("too many strings")
}
case class B(vs:String*) extends A {
override val variable: Seq[String] = vs
//override def hi(): Unit = ???
}
val b = B("x", "y", "z")
println(b)
This will throw error "A.variable() is null".
Strangely, if I wrote variable as given constructor parameter, the error is gone.
case class B(override val variable:String*) extends A {
//override def hi(): Unit = ???
}
How I can delay the "check" and why the second case doesn't throw exception?
That's a use case for early initializers
case class B(vs: String*) extends {
override val variable: Seq[String] = vs
} with A {
//override def hi(): Unit = ???
}
In Scala, what is an "early initializer"?
https://docs.scala-lang.org/scala3/reference/dropped-features/early-initializers.html
When I compile this code, I get ambiguous reference error for method m1. Can someone tell me why?
object MyClass {
trait T {
def m1(str: String): Unit = println(str)
def m1: Unit = {
println("m1")
m1("from:m1")
}
}
class C extends T {
override def m1(str: String): Unit = println(str+"1")
}
def main(args: Array[String]): Unit = {
val c = new C()
c.m1
}
}
When you call C.m1 in main you don't include parentheses. The compiler doesn't know if you are intentionally calling the arity-0 method, or were intending to call the arity-1 method using infix notation, eg c.m1 "hello".
Replacing c.m1 with c.m1() will compile.
I'm trying to add an implicit value to (what I believe is) the companion object of a case class, but this implicit value is not found.
I'm trying to achieve something like the following:
package mypackage
object Main {
def main(args: Array[String]): Unit = {
val caseClassInstance = MyCaseClass("string")
val out: DataOutput = ...
serialize(out, caseClassInstance)
// the above line makes the compiler complain that there is no
// Serializer[MyCaseClass] in scope
}
def serialize[T : Serializer](out: DataOutput, t: T): Unit = {
...
}
}
object MyCaseClass {
// implicits aren't found here
implicit val serializer: Serializer[MyCaseClase] = ...
}
case class MyCaseClass(s: String) {
// some other methods
}
I've explicitly added the package here to show that both the MyCaseClass case class and object should be in scope. I know that the object is actually being constructed because I can get this to compile if I add
implicit val serializer = MyCaseClass.serializer
to main (though notably not if I add import MyCaseClass.serializer).
I'm concerned that the MyCaseClass object is not actually a companion of the case class, because if I explicitly define apply and unapply on the object and then attempt to call MyCaseClass.apply("string") in main, the compiler gives the following error:
ambiguous reference to overloaded definition,
both method apply in object MyCaseClass of type (s: String)mypackage.MyCaseClass
and method apply in object MyCaseClass of type (s: String)mypackage.MyCaseClass
match argument types (String)
val a = InputRecord.apply("string")
^
If it's not possible to take this approach, is there a way to use type classes with case classes without creating an implicit value every time it must be brought into scope?
EDIT: I'm using scala 2.10.3.
EDIT 2: Here's the example fleshed out:
package mypackage
import java.io.{DataOutput, DataOutputStream}
object Main {
def main(args: Array[String]): Unit = {
val caseClassInstance = MyCaseClass("string")
val out: DataOutput = new DataOutputStream(System.out)
serialize(out, caseClassInstance)
// the above line makes the compiler complain that there is no
// Serializer[MyCaseClass] in scope
}
def serialize[T : Serializer](out: DataOutput, t: T): Unit = {
implicitly[Serializer[T]].write(out, t)
}
}
object MyCaseClass {
// implicits aren't found here
implicit val serializer: Serializer[MyCaseClass] = new Serializer[MyCaseClass] {
override def write(out: DataOutput, t: MyCaseClass): Unit = {
out.writeUTF(t.s)
}
}
}
case class MyCaseClass(s: String) {
// some other methods
}
trait Serializer[T] {
def write(out: DataOutput, t: T): Unit
}
This actually compiles, though. I am getting this issue when using Scoobi's WireFormat[T] instead of Serializer, but can't provide a concise, runnable example due to complexity and the Scoobi dependency. I will try to create a more relevant example, but it seems as though the issue is not as general as I thought.
It turns out that the type class instances actually need to be implicit values, rather than objects. The MyCaseClass object above works because its serializer is assigned to an implicit value. However, this implementation
object MyCaseClass {
implicit object MyCaseClassSerializer extends Serializer[MyCaseClass] {
override def write(out: DataOutput, t: MyCaseClass): Unit = {
out.writeUTF(t.s)
}
}
}
fails with the error
Main.scala:9: error: could not find implicit value for evidence parameter of type mypackage.Serializer[mypackage.MyCaseClass]
serialize(out, caseClassInstance)
^
In my real code, I was using an auxiliary function to generate the Serializer[T] (see https://github.com/NICTA/scoobi/blob/24f48008b193f4e87b9ec04d5c8736ce0725d006/src/main/scala/com/nicta/scoobi/core/WireFormat.scala#L137). Despite the function having its own explicit return type, the type of the assigned value was not being inferred correctly by the compiler.
Below is the full example from the question with such a Serializer-generator.
package mypackage
import java.io.{DataOutput, DataOutputStream}
object Main {
import Serializer._
def main(args: Array[String]): Unit = {
val caseClassInstance = MyCaseClass("string")
val out: DataOutput = new DataOutputStream(System.out)
serialize(out, caseClassInstance)
}
def serialize[T : Serializer](out: DataOutput, t: T): Unit = {
implicitly[Serializer[T]].write(out, t)
}
}
object MyCaseClass {
import Serializer._
// does not compile without Serializer[MyCaseClass] type annotation
implicit val serializer: Serializer[MyCaseClass] =
mkCaseSerializer(MyCaseClass.apply _, MyCaseClass.unapply _)
}
case class MyCaseClass(s: String)
trait Serializer[T] {
def write(out: DataOutput, t: T): Unit
}
object Serializer {
// does not compile without Serializer[String] type annotation
implicit val stringSerializer: Serializer[String] = new Serializer[String] {
override def write(out: DataOutput, s: String): Unit = {
out.writeUTF(s)
}
}
class CaseClassSerializer[T, A : Serializer](
apply: A => T, unapply: T => Option[A]) extends Serializer[T] {
override def write(out: DataOutput, t: T): Unit = {
implicitly[Serializer[A]].write(out, unapply(t).get)
}
}
def mkCaseSerializer[T, A : Serializer]
(apply: A => T, unapply: T => Option[A]): Serializer[T] =
new CaseClassSerializer(apply, unapply)
}
This related, simple code below prints 1.
object A{
implicit def A2Int(a:A)=a.i1
}
case class A(i1:Int,i2:Int)
object Run extends App{
val a=A(1,2)
val i:Int=a
println(i)
}
I've found extremely weird behaviour (scala 2.9.1 ) using and defining implicit values, and wondering if anyone can explain it, or if it's a scala bug?
I've created a self contained example:
object AnnoyingObjectForNoPurpose {
trait Printer[T] {
def doPrint(v: T): Unit
}
def print[T : Printer](v: T) = implicitly[Printer[T]].doPrint(v)
trait DelayedRunner extends DelayedInit {
def delayedInit(x: => Unit){ x }
}
// this works, as it should
object Normal extends DelayedRunner {
implicit val imp = new Printer[Int] {
def doPrint(v: Int) = println(v + " should work")
}
print(343)
}
// this compiles, but it shouldn't
// and won't run, cause the implicit is still null
object FalsePositive extends DelayedRunner {
print(123)
implicit val imp = new Printer[Int] {
def doPrint(v: Int) = println(v + " should not compile")
}
}
def main(args: Array[String]) {
implicit val imp = new Printer[Int] {
def doPrint(v: Int) = println(v + " should work")
}
print(44)
// print(33.0) // correctly doesn't work
Normal // force it to run
FalsePositive // force this to run too
}
}
Suppose you changed your definition of delayInit to be a no-op, i.e.
def delayedInit(x: => Unit) { }
Then in your main method do something like
println("FP.imp: " + FalsePositive.imp)
As expected that will print FP.imp: null, but the real point of the exercise is to illustrate that the block that defines the body of FalsePositive is acting like a regular class body, not a function body. It's defining public members when it sees val, not local variables.
If you added a method to AnnoyingObjectForNoPurpose like the following, it wouldn't compile because print's implicit requirement isn't satisfied.
def fails {
print(321)
implicit val cantSeeIt = new Printer[Int] {
def doPrint(v: Int) = println(v + " doesn't compile")
}
}
However if you defined a class along the same principle, it would compile, but fail at runtime when initialized, just like your FalsePositive example.
class Fine {
print(321)
implicit val willBeNull = new Printer[Int] {
def doPrint(v: Int) = println(v + " compiles, but fails")
}
}
To be clear, the compile behavior of Fine has nothing to do with the presence of the implicit. Class/object initializers are very happy to compile with val initializers which reference undefined vals.
object Boring {
val b = a
val a = 1
println("a=%s b=%s".format(a, b))
}
Boring compiles just fine and when it is referenced, it prints a=1 b=0
It seems like your question boils down to "Should the body of a class/object deriving from DelayedInit be compiled as if it's a class body or a function block?"
It looks like Odersky picked the former, but you're hoping for the latter.
That's the same bug as if I write this:
object Foo {
println(x)
val x = 5
}
It ain't a bug. Your constructor flows down the object body and happens in order. DelayedInit isn't the cause. This is why you need to be careful when using val/vars and ensure they init first. This is also why people use lazy val's to resolve initialization order issues.
Is there a way to pass an implicit parameter into a curried function. I am using a dirty fix (se below) but it is not pretty. I would love to be able to pass the implicit var "i" as a implicit param.
case class myLoaner() {
implicit val i = "How to get this val into scope within the session function"
def withCode[T](session: => T): Either[Exception, T] = {
try {
Right(session)
} catch {
case ex: Exception => {
Left(ex)
}
}
}
}
object Test {
def main(args: Array[String]) {
val r = myLoaner()
r.withCode {
implicit val imp = r.i // I want to get rid of this line of code and use the implict val defined above directly
val h = new Helper
h.run
}
}
class Helper {
def run(implicit i: String) {
println(i)
}
}
}
After val r = myLoaner(), you can write
import r.i
or
import r._
to do what you want. Alternatively, you can mark r itself implicit and provide this extra definition:
implicit def loanerString(implicit loaner: myLoaner): String = loaner.i
... but now a little bit too many implicits start floating around for my taste, so use that wisely. Sometimes too much implicit magic harms the readability and understandability of your code.
You can always pass implicit parameters directly, e.g. as h.run(r.i).