Scala named argument: recursive call - scala

Very strange situation.
I have the following code snippet:
case class SomeResponse(
ok: Boolean,
result: Seq[Data]
)
class TestContainer {
def testMethod() = {
val response = SomeResponse(
// vvv - issue is here
ok = true, Seq(getStubData)
// ^^^
)
val result = Json.toJson(response)
}
def getStubData = Data(10, "James")
}
When I am not specifying parameter name, everything compiles and works as expected.
But when I explicitly set parameter name
val response = SomeResponse(
// vvv - issue is here
ok = true, result = Seq(getStubData)
// ^^^
compiler complies with the following message:
Error:(63, 30) recursive value response needs type
val result = Json.toJson(response)
Is there any specific compiler behavior for named arguments?

This is the result of the interaction between a semi-solved issue in scala and another one in sbt:
scala/bug#5091
sbt/sbt#1928
Judging by the comments there and in linked issues, during type inference the compiler treats all x = y statements in the same way, leading to a cycle when trying to infer result above.
Workarounds:
provide the explicit type of result or even response above; anything that will break the type inference cycle will do
rename val result

Related

Return first element of array, in a def

Can you please help me understand, why the second def is not compiling, and how to write the second def for that it is compiling (return first entry of Array in one line). Thanks!
import java.awt.{GraphicsDevice, GraphicsEnvironment}
class SeparatedTestCase {
def does_compile: GraphicsDevice = {
val ge: GraphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment
val devices: Array[GraphicsDevice] = ge.getScreenDevices
devices(0)
}
def does_not_compile: GraphicsDevice = {
val ge: GraphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment
val device0: GraphicsDevice = (ge.getScreenDevices)(0) // <---- compile error
device0
}
}
//Error:(13, 59) no arguments allowed for nullary method getScreenDevices: ()Array[java.awt.GraphicsDevice]
//val device0: GraphicsDevice = (ge.getScreenDevices)(0)
You have to invoke the method with explicit parentheses:
ge.getScreenDevices()(0)
This does not compile, because your second invocation means the same as
ge.getScreenDevices(0)
which does not do what you want because getScreenDevices is a Java null-ary method which can be invoked either with parentheses or not, and if you specify one set of parentheses, Scala assumes that you want to invoke this method with these parameters, which of course won't work since it does not accept any arguments.

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.

Use method with default parameter in map

I want to map a stream of Doubles to a method which takes two parameters, one of them has a default value. I want to use the default parameter so my method has only 1 parameter which I need to pass:
def pow(x:Double, exponent:Double=2.0) = {
math.pow(x,exponent)
}
I've found out that the following works, but I do not understand why:
val res = (1 to 100).map(_.toDouble).map(pow(_))
I'm especially confused because the following does not work (compiler error because of missing type information):
val pow2 = pow(_)
val res = pow2(2.0)
println(res) // expect 4.0
The compiler is not able to infer the type that you will provide to pow2. In the res mapping you explicitly feed it a collection of Doublesand therefore pow(_) does not complain. However, in the case of val pow2 = pow(_) it complains that type parameter is missing. Change it to
val pow2 = pow(_: Double)
val res = pow2(2.0)
println(res)
and it will work just fine. pow(_) will be expanded two x => pow(x) and at this point the compiler cannot infere what's x without the type annotation.

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> =.

When is a scala partial function not a partial function?

While creating a map of String to partial functions I ran into unexpected behavior. When I create a partial function as a map element it works fine. When I allocate to a val it invokes instead. Trying to invoke the check generates an error. Is this expected? Am I doing something dumb? Comment out the check() to see the invocation. I am using scala 2.7.7
def PartialFunctionProblem() = {
def dream()() = {
println("~Dream~");
new Exception().printStackTrace()
}
val map = scala.collection.mutable.HashMap[String,()=>Unit]()
map("dream") = dream() // partial function
map("dream")() // invokes as expected
val check = dream() // unexpected invocation
check() // error: check of type Unit does not take parameters
}
For convenience, Scala lets you omit empty parens when calling a method, but it's clever enough to see that the expected type in the first case is ()=>Unit, so it doesn't remove all the parens for you; instead, it converts the method into a function for you.
In the val check case, however, it looks just like a function call result getting assigned to a variable. In fact, all three of these do the exact same thing:
val check = dream
val check = dream()
val check = dream()()
If you want to turn the method into a function, you place _ after the method in place of the argument list(s). Thus,
val check = dream() _
will do what you want.
Well, the problem is that you got it all wrong. :-)
Here are some conceptual mistakes:
def dream()() = {
println("~Dream~");
new Exception().printStackTrace()
}
This is not a partial function. This is a curried method with two empty parameter lists which returns Unit.
val map = scala.collection.mutable.HashMap[String,()=>Unit]()
The type of the values in this map is not partial function, but function. Specifically, Function0[Unit]. A partial function would have type PartialFunction[T, R].
map("dream") = dream() // partial function
What happens here is that Scala converts the partially applied method into a function. This is not a simple assignment. Scala does the conversion because the type inferencer can guess the correct type.
val check = dream() // unexpected invocation
Here there's no expected type to help the type inferencer. However, empty parameter lists can be ommitted, so this is just a method call.