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.
Related
I have the following piece of Scala with ambigiuous implicits, which I would have thought should work, due to lower priority given to inherited implicits. But it does not - it fails with an ambiguous implicit values-error. Can someone explain to me why priorities does not work here?
trait Printer[-T] {
def prettify(instance:T): String
}
trait LowPriorityPrinter {
implicit val anyPrinter:Printer[Any] = new Printer[Any]{ def prettify(instance:Any) = instance.toString() }
}
object Printer extends LowPriorityPrinter {
implicit val intPrinter = new Printer[Int]{ def prettify(instance:Int) = instance.toString() }
}
object MyApp extends App {
def prettyprint[T](i:T)(implicit p:Printer[T]) = println(p.prettify(i))
prettyprint(234)
}
The issue is simple, but nasty. The LowPriorityPrinter catch all instance of your type class needs to be generic, not for Any:
object Printer {
implicit val intPrinter: Printer[Int] =
new Printer[T]{ def prettify(x: T) = x.toString() + " (int") }
implicit def anyPrinter[T]: Printer[T] =
new Printer[T]{ def prettify(x: T) = x.toString() + " (general) }
}
Basically, the literal 234 is just as much an Int as it as an Any and neither of those types is more specific than the other (so the priority trick is useless).
I'm trying to compile the following code, but the last line does not compile:
class SuperContainer (
val shapeSets: Set[MyContainer[Shape]] = Set.empty[MyContainer[Shape]]) {
def addAct(el: MyContainer[Shape]) = {
new SuperContainer(shapeSets + el)
}
}
class MyContainer[A](val ls: Set[A] = Set.empty[A]) {
def addElement(el: A) = {
new MyContainer(ls + el)
}
}
abstract class Shape
case class Circle(radius: Int) extends Shape {
override def toString = "Circle(" + radius + ")"
}
case class Square(s: Int) extends Shape {
override def toString = "Square(" + s + ")"
}
object MyContainer {
def main(args: Array[String]) {
//Circle Container
val myc1 = new MyContainer[Circle]()
val myc11 = myc1.addElement(new Circle(6))
//Square Container
val myc2 = new MyContainer[Square]()
val myc21 = myc2.addElement(new Square(6))
val scont = new SuperContainer
scont.addAct(myc11) //does not compile
}
}
Scala compiler suggests me to use +A in MyContainer class definition, but by doing that, other compile errors occur. Am I doing something wrong or this is just a Scala limitation? Is there any way to overcome this problem?
In order to achieve what you want, MyContainer has to be covariant:
class MyContainer[+A](val ls: Set[A] = Set.empty[A]) // ...
Now, your definition of addElement will cause an error, since A appears in contravariant position (as a function argument in this case). You will have to adapt your signature as follows:
def addElement[B >: A](el: B): MyContainer[B]
This makes sense if you think of it: If you have a Container[Circle] (which can be seen as a Container[Shape] due to covariance) and you add a Shape, you have a Container[Shape] at the end and not a Container[Circle].
The implementation of addElement will not change.
Further, you cannot make Set[A] available outside the class (i.e. you have to remove the val), since Set[A] is not covariant. If you want to access elements, you'll have to add additional methods to query the set.
class MyContainer[+A](ls: Set[A] = Set.empty[A]) // ...
UPDATE
This is to explain clearer, why Set[A] cannot be part of MyContainer[+A]'s public API. Say we have:
class A
class B extends A
Imagine the following:
val x: MyContainer[A] = new MyContainer[B]
We can do that due to the covariance. However, if we could call now:
val s = x.ls // get internal set
We expect s to be of type Set[A]. However, the internal Set of x is a Set[B] which is not a Set[A]. Therefore this is not correctly typed.
Scala 2.10:
class A(val x:Int=0) {
}
object A {
def apply(x:Int): A = new A(x) // works
def apply(): A = new A() // fails to compile
}
val b = A(123) // :-)
val a = A() // >-(
Solution?
Even though your code should work (I suspect some implicit argument being at work here)
you can simplify it by doing
object A {
def apply(x: Int=0): A = New A(x)
}
while being shorter there's the drawback of being less DRY
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).
I have a class that takes an implicit parameter which is used by functions called inside class methods. I want to be able to either override that implicit parameter, or alternatively, have the implicit argument be copied from its source. As an example:
def someMethod()(implicit p: List[Int]) {
// uses p
}
class A()(implicit x: List[Int]) {
implicit val other = List(3) // doesn't compile
def go() { // don't want to put implicit inside here since subclasses that override go() have to duplicate that
someMethod()
}
}
The behavior I want is that someMethod() gets an implicit parameter that is some changed version of x, which was the class's implicit parameter. I want to be able to either mutate x without changing it for whatever passed it into A's constructor, or otherwise override it to a new value of my choosing. Both approaches don't seem to work. That is, it doesn't copy the list in the former case, and the compiler finds an ambiguous implicit value for the latter case. Is there a way to do this?
I realize that I can redefine the implicit value within go(), but this is not a good choice in my case because this class is subclassed numerous times, and I'd like to handle this implicit change in the base class only. So it doesn't necessarily need to go in the constructor, but it must be in a method other than go().
Introduce another wrapper type, simply to disambiguate:
// badly named, choose something domain-specific
case class ListHolder(theList: List[Int])
def someMethod()(implicit holder: ListHolder) {
val xs = holder.theList
// uses xs ...
}
class A()(implicit xs: List[Int]) {
implicit val other = ListHolder(42 :: xs) // compiles
def go() {
// xs is never considered for the implicit param to someMethod()
// because it's now the wrong type
}
}
This also makes the code more self-documenting, as it becomes blindingly obvious that the two implicits are not one and the same.
If you want to have zillions of implicits floating around that don't collide with each other, you can create a wrapper class that you can tag with marker traits for implicit usage. There are a variety of syntaxes you could use; here's one example:
object Example {
class Implication[A,B](val value: A) {
def apply[C](c: C) = new Implication[C,B](c)
}
object Implication {
def mark[B] = new Implication[Unit,B](())
implicit def implication_to_value[A,B](i: Implication[A,B]) = i.value
}
trait One {}
trait Two {}
implicit val x = Implication.mark[One]("Hello")
implicit val y = Implication.mark[Two]("Hi")
def testOne(implicit s: Implication[String,One]) = println(s: String)
def testTwo(implicit s: Implication[String,Two]) = println(s: String)
def testThree(s: String) = println("String is " + s)
def main(args: Array[String]) {
testOne
testTwo
testThree(x)
testThree(y)
}
}
Which works as you would hope:
scala> Example.main(Array())
Hello
Hi
String is Hello
String is Hi
Since you have to use a wrapper object, it's not super-efficient, but it can be very effective. (Or very confusing, given how much happens implicitly.)
This modification compiles. I changed x into a var:
class A()(implicit var x: List[Int]) {
def someMethod()(implicit p: List[Int]) {
// uses p
}
x = List(3)
def go() { // don't want to put implicit inside here since subclasses that override go() have to duplicate that
someMethod()
}
}