`and/or` accept values that are not boolean

For example, we can write down

(and #t 1 0) ; 0
(and 1 #t 0) ; 0
(and 1 0 #t) ; #t
(or 0 #t #f) ; 0
(or #t 0 #f) ; #t
(or #t #f 0) ; #t

I think these are two questions

  1. why they accept non-boolean?
  2. how should I interpret results in the mind model?
1 Like

https://docs.racket-lang.org/guide/conditionals.html should be able to answer both of your questions.

4 Likes

emmm...yes, but still think it's weird XD.

The key thing here is that and and or are not logical operators.

They are instead "short-circuting" operators, which means they don't evaluate all arguments if the result is clear from the first arguments.

The or operation returns the first "true" (non-false) value.

> (or #f #t (/ 1 0))
#t

The evaluation was "short-circuited" in the sense that (/ 1 0) was never evaluated.

The second thing to keep in mind is that #f is the only false value and all other values count as true.
This variation of the first example shows that #t can be replaced with any non-false value:

> (or #f 42 (/ 1 0))
42

In short:

  • The or operation returns the first "true" (non-false) value.
  • If there are no "true" values, then the result is #f.
  • Arguments after the first "true" are not evaluated.

Similarly:

  • The and operation returns the last "true" value, if all arguments are "true".
  • If at least one argument is false, the result is #f.
  • If a false argument is found, the following arguments are not evaluated.

An common use of and is:

(and <check-some-condition> <evaluate-expression>)

where the expression would result in an error, of the condition isn't met.

See more on short-circuiting here:

4 Likes

One special case of

(and <check-some-condition> <evaluate-expression>)

that I find interesting is using

(and <some-value> #t)

to "convert" any "true" value to #t. In other words, with this expression the result will be either #t or #f (the latter if <some-value> is #f).

6 Likes