Rules for `? ? ?`, why is < not a member of Nothing

I had some old code, which I thought used to compile (not 100% sure) but after upgrading to scala 2.13 it doesn’t. It is basically a student template, which the student needs to replace the instances of ??? with a valid expression. The compiler complains that < is not a member of Nothing.

Did this ever work? or was it my imagination?

BTW how do we know < is not a member of Nothing? Every member of Nothing has such a member. Right?

    def recur(left:Double,right:Double,depth:Int):Option[Double] = {
      val mid = ???

      if ( ??? < ???)
        Some(???)
      else if (depth >= maxDepth)
        None
      else if ( f(mid))
        recur(???,???,???)
      else
        recur(???,???,???)
    }

Ahm no, there no even a single value Nothing to begin with.

That code should never compile and I guess that is ok, students need to fix the code anyways.

Exactly. EVERY. member of Nothing has a < method, because the set of such objects is empty. It seems to me that ???.<(???) should be valid, in the same sense that if(???) ... is valid.

Is Nothing a subtype of some type which as a < method?

The hope with ??? is that the code compiles and fails at runtime if the line is ever reached. If you have one single ??? in the project which fails to compile, then you cannot test anything in the entire project.

BTW why can’t I put ??? in the title of this thread? every time when I try, it gets replaced with a single ?

Nothing is a subtype of all types, so yes.

I do not see why, but I understand your frustration. You may try adding an extension method or maybe using type hints as suggested in the other thread.

That is valid because if expects a boolean and since Nothing <: Boolean then it is valid due Liskov.

Isn’t Nothing also a subtype of Int which has a < method?

Anyway, I’ve also discovered that ???:Int does not work either. :frowning:
I wanted to use something like (??? to ??? by ???).foldLeft(...) which complains that Nothing does not have a to member. So I tried (???:Int to ???:Int by ???:Int ).foldLeft(...) but that fails also.

Yes, but the compiler has no information, and not a single reason to infer Int in that context; so it just leaves the type as Nothing which doesn’t have that method.

If you use a real compiler you will see this error:

not found: value ???:

After that, you know any other error will be wrong.
Try with:

((??? : Int) to (??? : Int) by (??? : Int))

??? is a perfectly cromulent Double (and if you said ??? : Double it would compile) but Scala doesn’t search the universe to see if there’s something out there with a < method. What you’re trying to do makes logical sense but Scala just doesn’t work that way.

2 Likes

:laughing:

parens. alas there are so many possible paren placements.

cromulent? that’s a new one for me. But I’m going to start using. Cromulent is a perfectly cromulent word and should be in everyone’s vocabulary.

Isn’t that like peeking into an empty room and say “all persons in that room are male”? Which would lead to a logical inconstency since also “all persons in that room are not male” would be true, in other words “all persons in that room are both male and not male”.

There is no inconsistency. And this is exactly the answer(s) you’ll get from the Scala stdlib, as well:

val s: List[String] = Nil
println(s.forall(_.isEmpty))
println(s.forall(_.nonEmpty))
4 Likes

@kavedaa, as I understand it this is simply a feature of empty sets. If a set is empty and P is a proposition, then it is true that (if x is in the set then P(x) is true). For that statement to not be true, it would need to be possible to find an x such that P(x) is false, but no such x exists.

2 Likes

yes I see. I know (now) that it doesn’t work this way, and I know it is not the normal use case, but I wonder what would happen if the compiler allowed any method to be called and any member to be accessed on an object of type Nothing, because that is unreachable code, and could simply be optimized away–No need to even generate code for it.

SBCL (a commonly used Common Lisp compiler) emits a warning something like: deleting unreachable code.

This is the case already - just give me an object of type Nothing and I’ll show you. :grinning:

I don’t quite agree. The following code fails to compile. I would be better in my mind if it compiled with a warning.

if ( ??? < ??? )
   3
else
   4

again, I emphasise, that this is in no sense a high priority item, and probably very difficult to implement, and very few people would ever use it except in pedagogical examples.

This doesn’t seem to have come up previously in the conversation, but it’s worth pointing out: it would be meaningless to compile it.

Consider an important details: Scala allows you to define your own operators. So what does the method < mean? You’re assuming that it’s the less-than function on Int. But why couldn’t it be, say, the less-than method on String, which has a completely different meaning? Why couldn’t it mean a less-than function defined somewhere in the world, that requires an implicit parameter in order to compile?

Basically, if you open it up to the entire universe like this, it becomes undecideable – the compiler doesn’t have enough information to assign a meaning to that symbol. It could be any of a potentially infinite number of methods, with potentially different details…

1 Like