Harden semantics for and and or macros.

There was perviously a bit of fuzziness on returning false/nil
from these macros that has been removed.
This commit is contained in:
Calvin Rose 2020-03-06 08:36:21 -06:00
parent fbe8998ca8
commit 6123c41f13
2 changed files with 17 additions and 8 deletions

View File

@ -244,26 +244,30 @@
[(,not= :error (,fiber/status ,f)) ,r])))
(defmacro and
"Evaluates to the last argument if all preceding elements are true, otherwise
evaluates to false."
"Evaluates to the last argument if all preceding elements are truthy, otherwise
evaluates to the first falsey argument."
[& forms]
(var ret true)
(def len (length forms))
(var i len)
(while (> i 0)
(-- i)
(def v (in forms i))
(set ret (if (= ret true)
(in forms i)
(tuple 'if (in forms i) ret))))
v
(if (idempotent? v)
['if v ret v]
(do (def s (gensym))
['if ['def s v] ret s])))))
ret)
(defmacro or
"Evaluates to the last argument if all preceding elements are false, otherwise
evaluates to true."
"Evaluates to the last argument if all preceding elements are falsey, otherwise
evaluates to the first truthy element."
[& forms]
(var ret nil)
(def len (length forms))
(var i len)
(var i (- len 1))
(var ret (in forms i))
(while (> i 0)
(-- i)
(def fi (in forms i))

View File

@ -107,4 +107,9 @@
(assert (= nil (match [1 2] [a b c] a)) "match 4")
(assert (= 2 (match [1 2] [a b] b)) "match 5")
# And/or checks
(assert (= false (and false false)) "and 1")
(assert (= false (or false false)) "or 1")
(end-suite)