The following code throws IllegalArgumentException:
trait T{
val x: Long
require(x > 0)
}
object T extends App{
val y = new T{ val x = 42L }
}
while the following does not:
trait T{
def x(): Long
require(x() > 0)
}
object T extends App{
val y = new T{ def x() = 42L }
}
Why is that? When is require() called? Why is the val even defined at that point?
Because def declares a method, which is put in the class by the compiler, so it exists as soon as it is compiled. In order to return something, a method has to run through to the point at which it actually returns something, so there is no problem in your second example.
val declares an "immutable value", although it still has to be initialised, before which point it holds the default value for its type - in this case, 0. This initialisation takes place after the constructor of trait T runs, unless you change your example to use early initialization:
val y = new { val x = 42L } with T
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
I have a use case similar to the situation following:
trait A {
implicit val x = "hello"
}
class B {
// somehow bring x into scope here???
def run(x: Int)(implicit y: String) = y + x
}
println((new B).run(3))
I understand that I need to bring x defined in the trait in the implicit scope of B. I've already tried the following:
# attempt 1 #
class B extends A { .... } /// doesn't work
# attempt 2 #
class B extends A {
val x1 = implicitly[String] /// doesn't work either
def run(x: Int)(implicit y: String) = y + x
}
Please explain what am I missing here (or, point me to relevant theory topic which I can study, fairly new to scala).
The value of 'implicit y' will be resolved in your println-line where it is not available. You are making the variable implicitly available within the body of the class, but resolution of implicit String is not needed there.
Implicit isn't magic; if you can't reach the implicit variable explicitly then so can't the compiler.
What problem are you really trying to solve?
Wrap your whole code in a object and extend trait A in class B :
object P {
trait A {
implicit val x = "hello"
}
class B extends A {
def run(y: Int) = y + x
}
def f = println(new B().run(3))
}
Output :
scala> P.f
3hello
The type class pattern in Scala involves defining a trait such as:
trait Show[T] {
def show(obj: T): String
}
Then you can define instantiations of this type class as such:
object Show {
implicit val string = new Show[String] {
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
def show(obj: Boolean): String = obj.toString
}
}
The advantage of defining these instantiations for basic types in the companion object is that they are automatically in scope whenever the type class is concerned (roughly).
Functionally it would appear defining the instantiation as an implicit val or an implicit object does not change much.
Is there a difference? Is one way better than the other?
There is actually more than the type names between val and object.
You know, object in Scala is something like a singleton in Java.
Maybe you thought that both string and BooleanShow are in an object not a class so they have no difference, but that's not true.
They are val and object no matter what.
Try this in Scala REPL.
trait Show[T] {
def show(obj: T): String
}
object Show {
println("!! Show created")
implicit val string = new Show[String] {
println("!! string created")
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
println("!!BooleanShow created")
def show(obj: Boolean): String = obj.toString
}
}
If only the definition is done, then no printlns are executed afterwards, since Show is a singleton in effect. It's not created yet.
Next, execute Show in Scala REPL.
scala> Show
!! Show created
!! string created
res0: Show.type = Show$#35afff3b
You see, printlns in Show and Show.string were called, but the one in Show.BooleanShow was not.
You can execute Show.BooleanShow next in Scala REPL.
scala> Show.BooleanShow
!!BooleanShow created
res1: Show.BooleanShow.type = Show$BooleanShow$#18e419c5
Show.BooleanShow was initialized at last. It is a singleton, so it is lazy.
Basically, your question is the same as val and object inside a scala class? except that your val and object are defined in an object, but the linked question tries to find differences val and object defined in a class and the method in val uses reflection (but yours uses overriding, so no reflection is involved). implicit basically does not make difference in what they are.
I think you already know the difference between class and object. Further information can be found in the linked question.
Since they say always to use explicit types for implicits, prefer val over object.
Compare Why can't Scala find my typeclass instance defined implicitly in the companion object, when the typeclass is not in a dedicated source file? where it makes a difference.
Make it lazy if necessary.
Elaboration:
scala> trait T
defined trait T
scala> object X { implicitly[T] ; object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; object O extends T }
^
scala> object X { implicitly[T] ; implicit object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T }
^
scala> object X { implicitly[O.type] ; implicit object O extends T }
defined object X
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
^
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y: T = O }
defined object X
The inferred type of O is the singleton type O.type.
With val x = new X { } you are creating an anonymous subclass of X, whereas with object x extends X you create a "proper" subclass. I would think that the overhead of an object is minimal, and as #applicius points out, it has proper name. Therefore I suggest to go for the object in this case.
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.
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.