Something about nothing

I’m learning Julia from the manual and really enjoying the process. Occasionally I try to do something weird and useless with a new learned concept. Here is an example of it:

julia> nothing == nothing
true

Nice, as expected.

julia> nothing <= nothing 
ERROR: MethodError: no method matching isless(::Nothing, ::Nothing)

I understand why, but this is logically incorrect.

1 Like

What’s logically incorrect? Do you expect nothing to be no equal to anything or do you expect it to have an order?

If you are talking about <= must include == then no, one of them is talking about ordering while the other is not. They are used i completely different context. OTOH, if <= works I would expect == to work though.


Another way to say it, this is not math and the way different operators and concepts are overloaded is not going to be completely the same as math. FWIW, math has it’s own inconsistency in many concepts anyway depending on the field. A programming language is also going to make decisions based on what people should use, rather than what could possibly be made work. Throwing an error in cases where one of the answer could be given can often be good for catching errors.

2 Likes

a <= b is equivalent to a < b or a == b, therefore nothing <= nothing should be true. Not a big problem, though. I understand that it would be a bit cumbersome to implement.

Let’s just go with this,

The problem still exists, the error says

ERROR: MethodError: no method matching isless(::Nothing, ::Nothing)

The first condition cannot be evaluated.

Yes, that’s why I wrote I understand the source of this error. A fix is to implement isless(::Nothing, ::Nothing), which returns false.

Ah yes. I am sorry that I missed that part. Since I wrote that I’ve continued to think about it. Yeah, it’s interesting that you can define equality for any thing you want but it doesn’t necessarily imply that it should be able to be ordered. I guess maybe that’s the point that @yuyichao was making.

Except in this case we have a type Nothing with only one element nothing, if I understand correctly. For degenerate case like this, <, > can always return false. Multiple dispatch could be used to define it this way for single element types.

Another option is to apply equality test first, before ordering test in operators like <= or >=.

Probably worth reading this Wikipedia article and then explaining why you want Nothing to be ordinal rather than nominal: https://en.wikipedia.org/wiki/Level_of_measurement

3 Likes

I think the problem is orthogonal to ordinal/nominal dichotomy. The set has only one element, which is equal to itself and ordering can’t be defined on such a set. So it is a degenerate case of nominal, if you have to use this classification. The way <= is implemented now, is equivalent to: (is equal and the type is ordered) or is smaller. I prefer the simpler: is equal or is smaller.

Curious as to what you’d have to say about this case:

julia> 1 + im == 1 + im
true

julia> 1 + im <= 1 + im
ERROR: MethodError: no method matching isless(::Complex{Int64}, ::Complex{Int64})

I think that the programmer typing <= implies that they believe that ordering is defined for the types on which they’re operating.

This leads me to believe that throwing a method error here is good. It serves the purpose of catching bugs or misconceptions that the programmer may have.


Another way of phrasing it would be this:

You claim that it’s logically correct to say that

but I think you gloss over something important. a < b is undefined in this case. It’s not that

(a < b) == false

it’s that a < b is a statement without meaning, so claiming that

(nothing < nothing) or (nothing == nothing)

should evaluate to true is wrong, in my opinion because

undefined or true

is not the same thing as true.

17 Likes

That’s probably the best justification of having it as is. I was trying to find a compelling case where it would be really useful and I couldn’t find any.

2 Likes

I paid attention to this. My suggestion relied on a property of single element sets, which are strictly totally ordered (https://en.wikipedia.org/wiki/Total_order).

2 Likes

I wonder if this is the reason <= goes to (x < y) | (x == y) rather than (x == y) | (x < y), since I would imagine (perhaps falsely), that equality is implemented for more types than comparators?

But (and maybe I’m missing something here, perhaps in the distinction between missing/undefined), it seems that the three-valued logic implicit in using | there, isn’t the same as what’s indicated here:

because missing | true returns true

1 Like

Right, I purposefully wrote undefined there rather than missing, which is meant for cases where you could imagine that there is a valid value, but that value is missing. That is not what’s going on here, and the Julia object which best represents the point I was trying to make would be MethodError, because an operation < was applied to types for which it is not defined.

However, Paul’s point about total order for a singleton set is well taken, though we agree it does not appear to be useful in practice.

2 Likes

I am wondering what practical application you imagine for ordering singleton sets.

Also, a lot of methods for ::Nothing are undefined on purpose. The implicit message is that if you want it to behave like a number (to a certain extent), you should really be using missing. MethodErrors in this context are a feature, not a bug.

6 Likes

As I wrote earlier, I don’t see a compelling application. The best I could find is a case of vectors with elements of ordered type or nothing. Such vectors would be conveniently comparable even if elements at the same index happen to be nothing. There are of course dangers of such approach.

I’m not proposing anything in this post. I’m just learning a new language and this was something I wanted to find more about.

1 Like

As others have said, if you end up with this type of vector, there’s a good chance you’re using nothing when you should actually be using missing (or possibly NaN if you’re working with floats). Among the many great discussions on this topic, I put John Miles White’s issue post here among the top. Might be a bit tough since some of the language (eg Nullable) are out of date, but the whole discussion is great

Edit: wrong link

1 Like

It looks more appropriate, but I’m at Chapter 14 and haven’t gotten to that part yet. :grinning:

Fair enough :slightly_smiling_face:. Once you get there, report back and let us know if the behavior of nothing makes sense in that context.

I found it challenging at first because a lot of programming languages muddle these different concepts. Coming from python, where an empty list, Nothing and False could all have the same meaning, I struggled with some programming patterns - “Why not just figure out what I mean, julia?!” But over time I’ve come to really appreciate the separation of these concerns, and the need to be explicit in dealing with the correct type.

8 Likes

This actually works already, because comparison of vectors only compares the corresponding element’s ordering when they’re not isequal.

julia> [1,nothing,1] < [1,nothing,2]
true
1 Like