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

1

6

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)
Vauntcourier answered 2/8, 2013 at 3:56 Comment(1)
could you post the signature of the lookup method on line 1. That's likely where the problem is. It's returning a Nothing instead of whatever it is that has the broadcast method.Wigley
Q
4

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

Quinsy answered 2/8, 2013 at 4:3 Comment(7)
Yes indeed. It boiled down to the compiler just not producing the correct class inference. I would not have guessed that - thank you!Vauntcourier
@mjk: java Inteface can't return Nothing without type parameter. Are you sure there is no type parameters in getDefault or in lookup? I've updated my answer.Quinsy
To be perfectly candid, I'm not sure of anything when it comes to the Atmosphere library. I've been wrestling its integration for a week and am at the point of being slap-happy.. That said, I dug this out of the library source files: public final Broadcaster lookup(Object id) which in turn makes a more robust call to one of the other override's. One thing that did baffle me, was the inability to chain those calls together - but my limited experience with Scala doesn't put me in a great position to tell you much more than that. Again, thank you. -cheersVauntcourier
@mjk: inability to chain those calls together: you should specify type parameter: BroadcasterFactory.getDefault().lookup[Broadcaster](_broadcasterId).broadcast(message).Quinsy
In all of the different examples I've come across, for all of the different version of the library, I don't recall ever seeing that form of type declaration used. Even more interesting, is that the code that I posted here is a distillation from a larger section/example from a scala web framework -- which worked fine there, but not when extracted and used from within my codebase. Any ideas what would cause that? (btw, I'm not implying that your examples are wrong in any way, just that I've never seen anyone else have to inject those declarations into theirs)Vauntcourier
@mjk: I guess all examples you mentioned are in java. There is actually type inference in java, a primitive one. In java there is no Nothing and you'll get the most common type in type inference for lookup method - Broadcaster. So you can use lookup without type specified. In scala you'll get the most specific type, and for lookup it's Nothing.Quinsy
Methods with return type Nothing don't necessarily eventually throw an exception - they could just loop forever, e.g. @scala.annotation.tailrec def f():Nothing = f()Spodumene

© 2022 - 2024 — McMap. All rights reserved.