Why are numeric comparisions constrained to support only two args?

Comparison ops are indeed functions, but when you chain them in code, they are expanded into a short-circuited structure.

julia> expand(:(1 < 2 < 3))
:(begin 
        unless 1 < 2 goto 3
        return 2 < 3
        3: 
        return false
    end)

All of these things are documented.

Getting back to your original question: proposals about basic features of the language are OK, but note that at this point the barrier to entry is high: they have to give a substantial advantage. In any case, putting in some work beforehand about understanding the language as is usually pays off.

1 Like

@Tamas_Papp
Fine, and why we could not expand && and || with the same trick and additionally use && and || as a function of two args like for numeric comparisions?

You are missing the point of || and &&: that they are not functions. This is key to their semantics.

@Tamas_Papp
This is clear to me, but why they are not functions?

You have | and & for that.

I thought & and | was binary only. Ok but the use of
&(true, false) gives me
ERROR: syntax: malformed expression
Stacktrace:
[1] macro expansion at ./REPL.jl:97 [inlined]
[2] (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:73

Do I have to escape something?

Right now you need (&)(x, y) to use & in a function call (you could assign another symbol to it and use that instead, though).

2 Likes

Well, booleans are single bit binary number so it works exactly the same.

You can also just use it as operator

And yet another reason &&/|| shouldn’t be functions (and to a less degree why allow multiarg < can be confusing) is that people will want to overload them. However, that overload will either not be called when it’s used as operator or it’ll conditionally turn off short circuit (C++) and both are really bad options (the latter being especially bad for a dynamically typed language like julia). Of course for comparison, you can already define multi-arg version that’ll not get called in a < b < c ...

@pabloferz
Thanks, it works now.

@yuyichao
I see the difference between && and &:
expand(:(1 & 1 & 1))
:((1 & 1) & 1)

, whereas
expand(:(1 && 1 && 1))
:(begin
unless 1 goto 6
unless 1 goto 4
return 1
4:
return false
6:
return false
end)

The difference is, && is lazy whereas & strict in evaluation.

To preserve the lazyness of the numeric comparisions one has to introduce strict variants of it, but this will blow up the language.

Exactly. I don’t see why it would be a problem for a < b < c to be different (in short-circuit semantics, not in value) from (<)(a,b,c).

Usually not, until someone overloads multiarg <. It’s not really new although defining it in base will encourage this thought. It’s a bit unsatisfying but I’m kind of OK either way…