(def! scalar-equal? =)
;; A faster `and` macro which doesn't use `=` internally.
-(defmacro! and2 ; boolean
+(defmacro! bool-and ; boolean
(fn* [& xs] ; interpreted as logical values
(if (empty? xs)
true
- `(if ~(first xs) (and2 ~@(rest xs)) false))))
-(defmacro! or2 ; boolean
+ `(if ~(first xs) (bool-and ~@(rest xs)) false))))
+(defmacro! bool-or ; boolean
(fn* [& xs] ; interpreted as logical values
(if (empty? xs)
false
- `(if ~(first xs) true (or2 ~@(rest xs))))))
+ `(if ~(first xs) true (bool-or ~@(rest xs))))))
(def! starts-with?
(fn* [a b]
- (or2 (empty? a)
- (and2 (mal-equal? (first a) (first b))
- (starts-with? (rest a) (rest b))))))
+ (bool-or (empty? a)
+ (bool-and (mal-equal? (first a) (first b))
+ (starts-with? (rest a) (rest b))))))
(def! hash-map-vals-equal?
(fn* [a b map-keys]
- (or2 (empty? map-keys)
- (let* [key (first map-keys)]
- (and2 (contains? b key)
- (mal-equal? (get a key) (get b key))
- (hash-map-vals-equal? a b (rest map-keys)))))))
+ (bool-or (empty? map-keys)
+ (let* [key (first map-keys)]
+ (bool-and (contains? b key)
+ (mal-equal? (get a key) (get b key))
+ (hash-map-vals-equal? a b (rest map-keys)))))))
;; This implements = in pure mal (using only scalar-equal? as native impl)
(def! mal-equal?
(cond
(sequential? a)
- (and2 (sequential? b)
- (scalar-equal? (count a) (count b))
- (starts-with? a b))
+ (bool-and (sequential? b)
+ (scalar-equal? (count a) (count b))
+ (starts-with? a b))
(map? a)
(let* [keys-a (keys a)]
- (and2 (map? b)
- (scalar-equal? (count keys-a) (count (keys b)))
- (hash-map-vals-equal? a b keys-a)))
+ (bool-and (map? b)
+ (scalar-equal? (count keys-a) (count (keys b)))
+ (hash-map-vals-equal? a b keys-a)))
true
(scalar-equal? a b))))
(def! hash-map-equality-correct?
(fn* []
(try*
- (and2 (= {:a 1} {:a 1})
- (not (= {:a 1} {:a 1 :b 2})))
+ (bool-and (= {:a 1} {:a 1})
+ (not (= {:a 1} {:a 1 :b 2})))
(catch* _ false))))
(def! sequence-equality-correct?
(fn* []
(try*
- (and2 (= [:a :b] (list :a :b))
- (not (= [:a :b] [:a :b :c])))
+ (bool-and (= [:a :b] (list :a :b))
+ (not (= [:a :b] [:a :b :c])))
(catch* _ false))))
;; If the native `=` implementation doesn't support sequences or hash-maps
;; correctly, replace it with the pure mal implementation
-(if (not (and2 (hash-map-equality-correct?) (sequence-equality-correct?)))
+(if (not (bool-and (hash-map-equality-correct?)
+ (sequence-equality-correct?)))
(do
(def! = mal-equal?)
(println "equality.mal: Replaced = with pure mal implementation")))