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)
mjk
  • 659
  • 1
  • 9
  • 20
  • 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. – Ratan Sebastian Aug 02 '13 at 04:03

1 Answers1

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

senia
  • 37,745
  • 4
  • 88
  • 129
  • Yes indeed. It boiled down to the compiler just not producing the correct class inference. I would not have guessed that - thank you! – mjk Aug 02 '13 at 04:21
  • @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. – senia Aug 02 '13 at 04:26
  • 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. -cheers – mjk Aug 02 '13 at 04:31
  • @mjk: `inability to chain those calls together`: you should specify type parameter: `BroadcasterFactory.getDefault().lookup[Broadcaster](_broadcasterId).broadcast(message)`. – senia Aug 02 '13 at 04:55
  • 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) – mjk Aug 02 '13 at 04:56
  • @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`. – senia Aug 02 '13 at 05:32
  • 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()` – fblundun Mar 17 '16 at 10:56