Skip to content
Kavachकवच

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
comparison.kav: Kavach code, then what running it prints

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)
triple-eq.kav: Kavach code, then what running it prints

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
chain.kav: Kavach code, then what running it prints
  • a == b == 5 is a == b and b == 5: all three are equal.
  • a == b != c is a == b and b != c.
  • Only neighbours are compared. a != c != b is true although a and b are equal: it checks a != c and c != b, never a against b.
  • 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 == g has 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

Case, text order and other cases worth knowing
ComparisonMeansResult
"Asha" == "asha"Case counts: Capital and small letters are different lettersfalse
"Asha".lower() == "asha".lower()Ignoring case: Bring both sides to small letters firsttrue
"apple" < "banana"Text order: Text compares letter by letter, as in a dictionarytrue
"Zebra" < "apple"Capitals first: Letters compare by their character code, so every capital comes before every small lettertrue
"10" < "9"Digits in text: Text compares character by character, so "10" comes before "9"true
10 < 9Numbers by value: Numbers compare as numbersfalse
'a' < 'b'Characters: One character against another, by its codetrue
"\u{e9}" == "e\u{301}"Same look, different text: é as one character and as e plus an accent are different text: text is not normalizedfalse
missing == noneMissing values: none equals nonetrue
User(name: "Asha") == User(name: "Asha")Records: Equal when all their fields are equaltrue

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(…)`
int-float.kav: Kavach code, then what running it prints

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 != c is a == b and b != c. No and to forget.

    decision 0040

  • == 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.

    decision 0039

  • Warnings on comparisons that rarely mean what they say

    == between computed floats, and x % 2 == 1 (which misses negative odd numbers), get a warning with the fix.

    spec 1.8

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).