Set a private var by an anonymous class in Scala? - scala

I found an example about abstract type member in Odersky's paper (Chapter 2.1): http://lampwww.epfl.ch/~odersky/papers/ScalableComponent.pdf
I paste it below
abstract class AbsCell {
type T
val init: T
private var value: T = init
def get: T = value
def set(x:T):Unit = {value = x}
}
val cell = new AbsCell{ type T=Int; val init=1}
cell.set(cell.get + 1)
cell.get
The codes doesn't work as expected in the latest Scala (Scala Version: 2.11).
I found the value of the last expression cell.get is 1, while what I expected is 2. The reason is that the private var value: T = init doesn't work well for the mixin anonymous class { type T=Int; val init=1}.
Does anyone have any ideas about this?

Your code doesn't work because value is initialized before the val init is. So at the time value is initialized, init is still equal to the default value of type T, which is 0 for T = Int.
You can fix this by making init a def or a lazy val.
Note that the paper you reference does not have the code you mention. In the paper, init is a parameter to the constructor of GenCell/AbsCell, and is therefore initialized properly before value is.

Related

Strange behavior of Scala compiler when initializing a class with a lazy argument

How possible that the first is correct Scala code but the second won't even compile?
The one that does compile
object First {
class ABC(body: => Unit) {
val a = 1
val b = 2
println(body)
}
def main(args: Array[String]): Unit = {
val x = new ABC {
a + b
}
}
}
This one doesn't compile on Scala 2.11 and 2.12
object Second {
class ABC(body: => Int) {
val a = 1
val b = 2
println(body)
}
def main(args: Array[String]): Unit = {
val x = new ABC {
a + b
}
}
}
It's not strange at all. Let's look at the first example:
You declare your class ABC to receive a pass by name parameter that returns Unit and you think this snippet:
val x = new ABC {
a + b
}
is passing that body parameter, it isn't.What's really happening is:
val x = new ABC(()) { a + b }
If you run that code you will see that println(body) prints () because you're not passing a value for your body parameter, the compiler allows it to compile because as the scaladoc states there is only 1 value of type Unit:
Unit is a subtype of scala.AnyVal. There is only one value of type Unit, (), and it is not represented by any object in the underlying runtime system. A method with return type Unit is analogous to a Java method which is declared void.
Since there is only one value the compiler allows you to omit it and it will fill in the gap. This doesn't happen with singleton objects because they don't extend AnyVal. Just has the default value for Int is 0 the default value for Unit is () and because there is only this value available the compiler accepts it.
From documentation:
If ee has some value type and the expected type is Unit, ee is converted to the expected type by embedding it in the term { ee; () }.
Singleton objects don't extend AnyVal so they don't get treated the same.
When you use syntax like:
new ABC {
// Here comes code that gets executed after the constructor code.
// Code here can returns Unit by default because a constructor always
// returns the type it is constructing.
}
You're merely adding things to the constructor body, you are not passing parameters.
The second example doesn't compile because the compiler cannot infer a default value for body: => Int thus you have to explicitly pass it.
Conclusion
Code inside brackets to a constructor is not the same as passing a parameter. It might look the same in same cases, but that's due to "magic".
You cannot pass a single argument to a constructor in curly braces, because this would be parsed as defining an anonymous class. If you want to do this, you need to enclose the curly braces in normal braces as well, like this:
new ABC({
a + b
})
As for why does compiler accept new ABC {a + b}, the explanation is a bit intricate and unexpected:
new ABC {...} is equivalent to new ABC() {...}
new ABC() can be parsed as new ABC(()) because of automatic tupling, which is a feature of the parser not mentioned in the specs, see SI-3583 Spec doesn't mention automatic tupling. The same feature casues the following code to compile without an error:
def f(a: Unit) = {}
f()
def g(a: (Int, Int)) = {}
g(0,1)
Note the call produces a warning (even your original example does):
Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want.
The warning is produced since 2.11, see issue SI-8035 Deprecate automatic () insertion.

Clarification over Scala polymorphism

On a recent worksheet I was presented with the question asking what would be the output of the following code:
class A { def m(x:Double) = x+x }
class B[Any] extends A{ def m(x: Any) = print(x) }
class C[Any] { def m (x:Double) = x+x; def m (x: Any) = print(x) }
val obj1 = new B[Int]; val obj2 = new C[Any]
obj1.m(1); obj1.m(2.3); obj2.m(4); obj2.m(5.6)
I'm quite confused as to what having a concrete type in the square brackets after the class name would mean (i.e. class B[Any]). Is the later expression val obj1 = new B[Int] valid because Int <: Any, Int being a subclass of Any?
When later running the code snippet, the result given was simply "1" being printed. This was not what I had expected the call to obj.m(2.3) to resolve at def m(x: any), where it seems in actuality the compiler went up to A and called the m in class A.
The later expressions, obj2.m(4) and obj2.m(5.6) seems to make sense as both 4 and 5.6 would land in the function with def m(x: Double), thus not print anything out.
In what order exactly does the compiler traverse to find what to call? I'd be very grateful if someone could clear up my confusions with how polymorphism is handled here by Scala, thank you very much :)
When you do class B[Any], you define a class with a type parameter called Any. Don't confuse the type parameter name with the actual class Any. You are just shadowing its name.
You could just as fine do this:
class B[Int]
val obj = new B[String]
You may see why it is bad practice to name type parameters after actual types. Usually, people use single letter names for their type parameters, like this:
class B[T] // I just changed the name of the type parameter from "Int" to "T".
val obj = new B[String]

Kotlin type inference fails for guava TreeMultimap

I have:
data class Edge(val spec: String, val weight: Int)
private val graph: SortedSetMultimap<String, Edge> = TreeMultimap.create()
The call to create() is an error:
MapCrawler.kt: (63, 71): Type inference failed. Expected type mismatch: inferred type is TreeMultimap<(???..???), (???..???)>! but SortedSetMultimap was expected
If I change it to be a
SortedSetMultimap<String, String>
it works fine (no issues with the type inference). In other words, this line compiles just fine:
private val graph: SortedSetMultimap<String, String> = TreeMultimap.create()
What is it about the Edge class that messes up the type inference, and how do I fix it?
You need to pass two comparator implementation to create function.
Have a look at following snippet:
private val graph:SortedSetMultimap<String, Food> = TreeMultimap.create(Comparator<String> { str1, str2 -> 0
// compare string here
}, Comparator<Food> { edge1, edge2 -> 0
// compare Edge object here
})
I have tested this it works. You can remove data type (:SortedSetMultimap<String, Food>) as assignment statement can infer which type of value is being returned.
Hope this helps.

Scala - how to go resolve "Value is not a member of Nothing" error

This example code is based on Atmosphere classes, but if someone could give me some insights into what the error means in general, I think I can figure out any Atmosphere-specific solution...
val bc = BroadcasterFactory.getDefault().lookup(_broadcasterId)
bc.broadcast(message)
After the first line, bc should contain a handle to an object whose class definition includes the method broadcast() -- in fact, it contains several overloaded variations. However, the compiler chokes on the second line of code with the following: "value broadcast is not a member of Nothing"
Any ideas/suggestions on what would be causing this?
Thanks.
EDIT: signature for [BroadcasterFactor].lookup :
abstract Broadcaster lookup(Object id)
Note: 1) that is the signature version that I've used in the example, 2) it is the java Inteface signature - whereas the getDefault() hands back an instantiated object that implements that interface.
Solution: force type cast on value:
val bc: Broadcaster = BroadcasterFactory.getDefault().lookup(_broadcasterId)
Nothing is the type name. It's the subtype of all other types. You can't call methods from Nothing itself, you have to specify exact type ((bc: ExactType).broadcast(message)). Nothing has no instances. Method, that returns Nothing will, actually, never return value. It will throw an exception eventually.
Type inference
Definition of lookup:
abstract public <T extends Broadcaster> T lookup(Object id);
in scala this definition looks this way:
def lookup[T <: Broadcaster](Object id): T
There is not specified type parameter in lookup method. In this case compiler will infer this type parameter as the most specific type - Nothing:
scala> def test[T](i: Int): T = ???
test: [T](i: Int)T
scala> lazy val x = test(1)
x: Nothing = <lazy>
scala> lazy val x = test[String](1)
x: String = <lazy>
You could specify type parameter like this:
val bc = BroadcasterFactory.getDefault().lookup[Broadcaster](_broadcasterId)
Draft implementation
In development process lookup can be "implemented" like this:
def lookup(...) = ???
??? returns Nothing.
You should specify either result type of lookup method like this: def lookup(...): <TypeHere> = ... or type of bc: val bc: <TypeHere> =.

Scala class members and constructor parameters name clash

Consider the following class written in Java:
class NonNegativeDouble {
private final double value;
public NonNegativeDouble(double value) {
this.value = Math.abs(value);
}
public double getValue() { return value; }
}
It defines a final field called value that is initialized in the constructor, by taking its parameter called alike and applying a function to it.
I want to write something similar to it in Scala. At first, I tried:
class NonNegativeDouble(value: Double) {
def value = Math.abs(value)
}
But the compiler complains: error: overloaded method value needs result type
Obviously the compiler thinks that the expression value inside the expression Math.abs(value) refers to the method being defined. Therefore, the method being defined is recursive, so I need to state its return type. So, the code I wrote does not do what I expected it to do: I wanted value inside Math.abs(value) to refer to the constructor parameter value, and not to the method being defined. It is as if the compiler implicitly added a this. to Math.abs(this.value).
Adding val or var (or private ... variants) to the constructor parameter doesn't seem to help.
So, my question is: can I define a property with the same name as a constructor parameter, but maybe a different value? If so, how? If not, why?
Thanks!
No, you can't. In Scala, constructor parameters are properties, so it makes no sense to redefine them.
The solution, naturally, is to use another name:
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
Used like this, initValue won't be part of the instances created. However, if you use it in a def or a pattern matching declaration, then it becomes a part of every instance of the class.
#Daniel C. Sobral
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
your code is right, but "constructor parameters are properties",this is not true.
A post from the official site said,
A parameter such as class Foo(x : Int) is turned into a field if it is
referenced in one or more methods
And Martin's reply confirms its truth:
That's all true, but it should be treated as an implementation
technique. That's why the spec is silent about it.
So normally, we can still treat primary constructor parameters as normal method parameter, but when the parameters is referenced by any of the methods, the compiler will cleverly turn it into a private field.
If any formal parameter preceded by the val, the compiler generates an getter definition automatically.if var, generates a setter additionally. see the language speification section 5.3.
That's all about primary constructor parameters.
You can consider parametric field
class NonNegativeDouble(val value: Double, private val name: String ){
if (value < 0) throw new IllegalArgumentException("value cannot be negative")
override def toString =
"NonNegativeDouble(value = %s, name = %s)" format (value, name)
}
val tom = "Tom"
val k = -2.3
val a = new NonNegativeDouble(k.abs, tom)
a: NonNegativeDouble = NonNegativeDouble(value = 2.3, name = Tom)
a.value
res13: Double = 2.3
a.name
<console>:12: error: value name in class NonNegativeDouble cannot be accessed in NonNegativeDouble
a.name
val b = new NonNegativeDouble(k, tom)
java.lang.IllegalArgumentException: value cannot be negative
...
It's defines fields and parameters with the same names "value", "name".
You can add modifiers such as private ...
In the case of case classes it should be:
case class NonNegativeDouble(private val initValue: Double) {
val value = Math.abs(initValue)
def copy(value: Double = this.value) = NonNegativeDouble(value)
}
The implementation of copy is required to prevent the sintesized version of the compiler that will bind the initValue argument.
I expect that the compiler is smart enough to not retain the «extra space» for the initValue. I haven't verified this behaviour.