Search code examples
clojure

Logical truthness in Clojure


What does the true? says actually? (true? 0)=false. (if 0 "0 is true" "0 is false")=0 is true. Why this happens?


Solution

  • You are confusing two things:

    • the different values that there are in Clojure, and
    • the way that if and its progeny treat these values.

    true and 1 are values, and they are different:

    (= true 1) ; false
    

    But they have the same effect as first arguments to if:

    (if true "Hello!" "Goodbye.") ; "Hello!"
    
    (if 1 "Hello!" "Goodbye.") ; "Hello!"
    

    In fact, almost any first argument causes if to evaluate and return its second argument:

    (if + "Hello!" "Goodbye.") ; "Hello!"
    
    (if *ns* "Hello!" "Goodbye.") ; "Hello!"
    
    (if String "Hello!" "Goodbye.") ; "Hello!"
    

    There are only two values that cause if to evaluate and return its third argument. Those two values are false and nil.

    (if false "Hello!" "Goodbye.") ; "Goodbye."
    
    (if nil "Hello!" "Goodbye.") ; "Goodbye."
    

    If no third argument is supplied, it defaults to nil:

    (if false "Hello!") ; nil
    

    The same distinction between values applies to the other Clojure conditionals, which are - directly or indirectly - derived from if: if-not, when, when-not, and, or, &c. These are expressed as macros, so that, like if, they do not evaluate their arguments until they need to.

    To quote the official documentation

    (if test then else?)

    Evaluates test. If not the singular values nil or false, evaluates and yields then, otherwise, evaluates and yields else. If else is not supplied it defaults to nil. All of the other conditionals in Clojure are based upon the same logic, that is, nil and false constitute logical falsity, and everything else constitutes logical truth, and those meanings apply throughout.