Think the first example was the one referenced, i.e.
julia> all([])
true
Think the first example was the one referenced, i.e.
julia> all([])
true
If they were modular integers like Int64
, they would wrap with addition, no?
julia> typemax(Int) + 1
-9223372036854775808
julia> typemax(Bool) + true
2
thatâs just Vacuous truth - Wikipedia which is very common. The problem with Python is []
can be interpreted as Boolean, which Julia is very much not able to
Yeah, but I was ju saying the quote on âjulia does the same thingâ was mentioned only for the first example, and not the one you brought up.
thatâs exactly what I donât understand because the point of @ bkamins is the whole thing, not just all([])
being true or not. I donât see how âJulia is the sameâ when it literally is NOT
I also donât think the all([])
example is at all confusing/surprising. That has always been exactly what I wanted it to do; I have always wanted all
to mean that there are no exceptions (so all([]) == true
), and any
to mean that there is an exception (so any([]) == false
). Any other behavior Iâd find both surprising and annoying, as Iâd then be forced to add length checks on all my uses.
The other Python cases I find more surprising.
I know (and sadly had to use) a language which does that: IDL.
Does IDL also let you use integers in conditionals?
Yes, see the article linked. And why limiting to integers? They support floating point numbers too, both real and complex, but the rule for floating point numbers is different: zero is false, all the rest is true (complex numbers ignore the imaginary part, so there are plenty of falsy zeros). You get the best of both worlds! And appreciate this example from the article
IDL> print, 2 or 0.
2.00000
The literal 2
is somehow automatically converted to floating point, so it becomes true. You canât even guess what the code is doing by reading it. IDL is a such a nonsense language that it all makes sense.
Yes, that is why it is the first example in the list. This example is the one that most people get right even without having to run the code. For the next two examples - most people get them wrong in Python if they are asked to guess the results and often even struggle to explain the reason for output produced once they see it.
The point is: such expressions should be easy to reason about without having to run the code.
They look a lot more attractive if you use the dignified term âgeneralized booleansâ.
This is great. I love examples of language designs that maybe made some sense in a microcosm but then become totally bizarre when you step back and look at the whole.
Sad that you need the emoticon to make sure we all get that itâs sarcasm
Hm, interesting I must have misremembered that. Thatâs unfortunate. In that case, I am a bit more sympathetic to your POV here, though Iâd lean instead towards making true + true == false
.
As far as I understand, +
should be xor
and *
should be &
julia> true * false
false
In Base:
+(x::Bool, y::Bool) = Int(x) + Int(y)
-(x::Bool, y::Bool) = Int(x) - Int(y)
*(x::Bool, y::Bool) = x & y
Itâs not obvious why. But, Iâm sure it wasnât an arbitrary choice.
Itâs stated as
## do arithmetic as Int ##
+(x::Bool) = Int(x)
-(x::Bool) = -Int(x)
+(x::Bool, y::Bool) = Int(x) + Int(y)
-(x::Bool, y::Bool) = Int(x) - Int(y)
*(x::Bool, y::Bool) = x & y
^(x::Bool, y::Bool) = x | !y
^(x::Integer, y::Bool) = ifelse(y, x, one(x))
in bool.jl
Just like true & false == false
, right? true == 1
and false == 0
so this is all consistent.
Same with true + true == 2
since 2 mod 2 == 0 == false
. I just would have wanted addition on Bools to wrap around instead of widening.
Same with
true + true == 2
since2 mod 2 == 0 == false
.
But, exactly because it widens this doesnât make sense. Sure 2 mod 2 == 0 == false
, but the return type is Int
which doesnât follow mod 2 artithmetic. I mean, is there a more âpracticalâ reason for widening ?
I think to allow something like this
sum(rand(Bool, 1000)) # to count true's
Although a little unfortunate, because there is count
. Maybe there are more cases of use.
(Edit: easier example.)
Bool
s are often used as the âlowest typeâ form of 1/0 in order to prevent accidental type promotion, could this be a reason to define arithmetic the way itâs done? For example,
julia> I(2)
2Ă2 Diagonal{Bool, Vector{Bool}}:
1 â
â
1
produces a Bool matrix to make sure that, e.g., I(2)*B
does not promote the type to a wider type than the type of B
.