`a == b == c`

is a very nice construct. `a < b > c`

too. however julia allows `a != b != c`

, but i would call it contraintuitive, because it is true if `a == c`

. my thinking is that != should not allow this at all, for it lacks common sense meaning. but if it is allowed, i would suggest translate to a != b && a != c && b != c

Why? Even `a < b < c`

does not assume transitivity, it just happens that it is the case in most use cases.

```
julia> expand(:(a<b<c))
:(begin
unless a < b goto 3
return b < c
3:
return false
end)
```

It would seems strange to me that other relations should.

is there a use case in which < is not transitive?

@pint, I think @Evizeroâs point is that `<`

is an arbitrary user-defined function, so there is nothing (except for sanity) stopping you from defining a non-transitive `<`

. The `a < b < c`

implementation does not compare `a < c`

, it only compares `a < b`

and `b < c`

.

but that is an abuse of the operator. the != chain is incorrect even if i donât abuse the operator, in fact it gives surprising result even when used with numbers.

Here the problem would be the user that wrote the chain of `!=`

and expected it to mean something useful.

You wouldnât write that in mathematics expecting it to be meaningful, and so shouldnât write it in code either.

What would happen in your example here then?

Or a simpler example: What would `a <= b < c `

translate to, how do I compare `a`

and `c`

. Is there a operator promote or are all possibilities evaluated?

i donât see how `a <= b < c`

can lead to ambiguity.

I am not sure about even that â below is stylized code for an exercise I sometimes ask students to do, to show how people are not good at generating random numbers:

```
d1 = [rand(1:3, 3) for i in 1:100]
d2 = # ask people to write down "random" triples containing 1:3
twochanges(v) = v[1] != v[2] != v[3]
sum(twochanges(v) for v in d1) # will be lower
sum(twochanges(v) for v in d2) # people tend to favor sequences with changes
```

Note also that chaining works for arbitrary âcomparisonâ operators, including user-defined operators, and does not require transitivity. For example, consider the `â`

operator, which is a synonym for `isapprox`

. This comparison is not transitive, but can be chained:

```
julia> 1 â 1 + 1e-8 â 1 + 2e-8
true
julia> 1 â 1 + 2e-8
false
```

The behavior for `!=`

is consistent with the behavior for other comparison operators: chaining implies pairwise comparisons between adjacent terms only.

I hadnât even realized that `a == b == c`

was lowered that way, instead of how it would be in `C/C++`

and C-like languages.

I would have thought that it would mean something totally different, i.e. `(a == b) == c`

, which then return true if `c`

were either `Bool`

or something that converted to `true`

or `false`

and matched the result of `a == b`

.

This may be worth a note in the `C/C++`

differences section of the manual.

(Iâm not saying there is anything *wrong* with the way Julia handles this, just that it can be surprising, hence a desire for having pointed out in an appropriate part of documentation)

Ah, thanks! I also wasnât trying to imply that it wasnât well documented *somewhere*, just that it *might* be worth having a line in at least the C/C++ differences section (which I was the initial author of ages ago). What do you think of doing that? (and pointing a reference to the chaining comparisons section there also).

I know of course that chaining worked with `<`

, `<=`

, `>`

and `>=`

, just hadnât realized it worked for arbitrary operators (pretty cool, that!)

I must say that I find the current meaning of `a != b != c`

to be exactly what I intuitively expected, and I was thoroughly confused as to what you even meant at first.

I read it like this: `a`

is different from `b`

and `b`

is different from `c`

. So

```
julia> 1 != 2 != 1
true
```

is exactly as it should be. If you want to test pairwise inequality for all combinations, you would do `a != b != c != a`

.

Inequality is not a transitive property, so why do you expect transitive behavior?

I think youâre getting at the real problem with this kind of discussion: people donât all have the same intuitions, so debating intuitions doesnât generally lead to any improvements in language design.

It should be in all cases (as logic dictates), the expand you showed, only shows what the current implementations of Julia does.

In case when you do not have transitive, e.g. a < b > c, or != or the sneaky â (isapprox), then for the optimizer, should split up and optimize the left and right of it separately.

âso there is nothing (except for sanity) stopping you from defining a non-transitive <â

Can that possibility be disallowed so the optimizer does not have to consider that case?

I believe noâŚ but math has a way of surprising meâŚ I donât know half of itâŚ E.g. I didnât give this much though until I realized (with more advanced ânumbersâ they lose more properties):

For complex number (and matrices of anything, except trivial 1x1?) < is not defined. Other than that, I believe when < is defined, itâs always defined the same way. Otherwise, Iâm in troubleâŚ and I really need to know.

Youâre now actively spreading misinformation. Please stop.

A linked list chain where you define `a<b`

to mean `a`

is immediately to the left of `b`

? That sounds like a perfectly useful and valid dispatch for `<`

for which it wouldnât be transitive. As @stevengj noted, itâs just an operator, so you can do whatever is sensible with it.