Operators: Comparison
● Beginner4 min
== != < <= > >= compare two values and give a Bool. They chain, and == compares contents.
fn main() {
const age = 25
print(age == 25)
print(age != 30)
print(age >= 18)
print(18 <= age < 65)
print([1, 2] == [1, 2])
print(["a": 1, "b": 2] == ["b": 2, "a": 1])
}The program ran and printed:
kavach run comparison.kav
truetruetruetruetruetrue
There is one ==, and it compares contents, so JavaScript's === isn't needed, and is refused with the fix:
fn main() {
const a = 1
if a === 1 {
print("one")
}
}The compiler refused the program:
kavach run triple-eq.kav
error: Kavach has no `===`: write `==`, which compares values by their contents (spec 1.8)Chains
18 <= age < 65 means 18 <= age and age < 65, as in mathematics, and age is worked out only once. Any mix of comparisons chains, as long as you like:
fn main() {
const a = 5
const b = 5
const c = 7
print(a == b == 5)
print(a == b != c)
print(a <= b < c)
print(a != c != b)
}The program ran and printed:
kavach run chain.kav
truetruetruetrue
a == b == 5isa == b and b == 5: all three are equal.a == b != cisa == b and b != c.- Only neighbours are compared.
a != c != bis true althoughaandbare equal: it checksa != candc != b, neveraagainstb. - The chain stops at the first part that is false, and each value is worked out once.
- A chain can hold any number of values:
e < c < a == b < d < f == ghas seven. - Brackets group:
(a == b) != (c == d)works out each bracket first, then compares the two answers.
Contents, not places
== looks inside: two lists are equal when their items are, two maps when their entries are, in any order.
How comparisons behave
| Comparison | Means | Result |
|---|---|---|
"Asha" == "asha" | Case counts: Capital and small letters are different letters | false |
"Asha".lower() == "asha".lower() | Ignoring case: Bring both sides to small letters first | true |
"apple" < "banana" | Text order: Text compares letter by letter, as in a dictionary | true |
"Zebra" < "apple" | Capitals first: Letters compare by their character code, so every capital comes before every small letter | true |
"10" < "9" | Digits in text: Text compares character by character, so "10" comes before "9" | true |
10 < 9 | Numbers by value: Numbers compare as numbers | false |
'a' < 'b' | Characters: One character against another, by its code | true |
"\u{e9}" == "e\u{301}" | Same look, different text: é as one character and as e plus an accent are different text: text is not normalized | false |
missing == none | Missing values: none equals none | true |
User(name: "Asha") == User(name: "Asha") | Records: Equal when all their fields are equal | true |
Two kinds of number never compare silently: an Int against a Float is refused, with the fix:
fn main() {
const whole: Int = 1
const real: Float = 1.0
print(whole == real)
}The compiler refused the program:
kavach run int-float.kav
error: there are no implicit number conversions: expected `Int`, found `Float`; convert with `Int(…)`What Kavach does for you
Comparisons chain, as in mathematics
0 <= i < items.len()means both tests, and the middle is worked out once. Any mix chains:a == b != cisa == b and b != c. Noandto forget.== compares contents
Two lists are equal when their items are; two maps when their entries are, in any order. A copy that was never changed is equal in one step, without looking inside.
Warnings on comparisons that rarely mean what they say
==between computed floats, andx % 2 == 1(which misses negative odd numbers), get a warning with the fix.
Go deeper the why, for readers who want it
Two comparisons rarely mean what they say, and get a warning: == between floats worked out while the program runs (rounding makes them differ in the last bits; use a.near(b)), and x % 2 == 1, which misses negative odd numbers because -3 % 2 is -1 (write x % 2 != 0).