123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- "Provides macros for various comparison operators."
- (import core/base b)
- (import core/base (defun defmacro gensym and n with let* if get-idx list .. else get-idx car))
- (defun mk-quote (a) :hidden (list `unquote a))
- (defun mk-splice-quote (a) :hidden (list `unquote-splice a))
- (defmacro def-comparison (name names func-name &additional)
- "Def a comparison macro with the given NAME, which calls FUNC-NAME with two operands.
- ### Example:
- ```
- > (< 1 2 3)
- true
- > (< 1 4 3)
- false
- ```"
- :hidden
- (let* [(a (car names))
- (b (get-idx names 2))
- (sym (gensym))
- (len (gensym))
- (rest (get-idx names 3))]
- ;; Sit back and enjoy the quote/unquote awfulness.
- `(defmacro ,name (,a ,b ,{ :tag "symbol" :contents (.. "&" (get-idx rest :contents)) })
- ,@additional
- (with (,len (n ,rest))
- (cond
- [(b/= ,len 0) `(,,func-name ,,(mk-quote a) ,,(mk-quote b))]
- [else
- (with (,sym (gensym))
- ;; If we've got multiple values then cache b, as that will be reused in the next operator
- `(with (,,(mk-quote sym) ,,(mk-quote b))
- (if (,,func-name ,,(mk-quote a) ,,(mk-quote sym)) (,,name ,,(mk-quote sym) ,,(mk-splice-quote rest)) false)))])))))
- (def-comparison = (a b rest) b/=
- "Check whether A, B and all items in REST are equal.
- This will lazily evaluate each value: if A is not equal to B, then no
- subsequent arguments will be evaluated.
- ### Example:
- ```cl
- > (let [(a 1)
- . (b 2)]
- . (= 1 a b))
- out = false
- > (with (a 1)
- . (= a 1))
- out = true
- ```")
- (def-comparison /= (a b rest) b//=
- "Check whether A is not equal to B, B is not equal to the first element
- in REST, etc...
- This will lazily evaluate each value: if A is equal to B, then no
- subsequent arguments will be evaluated.
- ### Example:
- ```cl
- > (let [(a 1)
- . (b 2)]
- . (/= a b 1))
- out = true
- > (with (a 1)
- . (/= a 1))
- out = false
- ```")
- (def-comparison < (a b rest) b/<
- "Check whether A is smaller than B, B is smaller than the first element
- in REST, and so on for all subsequent arguments.
- This will lazily evaluate each value: if A is greater or equal to B,
- then no subsequent arguments will be evaluated.
- ### Example:
- ```cl
- > (with (a 3)
- . (< 1 a 5))
- out = true
- ```")
- (def-comparison > (a b rest) b/>
- "Check whether A is larger than B, B is larger than the first element
- in REST, and so on for all subsequent arguments.
- This will lazily evaluate each value: if A is smaller or equal to B,
- then no subsequent arguments will be evaluated.
- ### Example:
- ```cl
- > (with (a 3)
- . (> 5 a 1))
- out = true
- ```")
- (def-comparison <= (a b rest) b/<=
- "Check whether A is smaller or equal to B, B is smaller or equal to the
- first element in REST, and so on for all subsequent arguments.
- This will lazily evaluate each value: if A is larger than B,
- then no subsequent arguments will be evaluated.
- ### Example:
- ```cl
- > (with (a 3)
- . (<= 1 a 5))
- out = true
- ```")
- (def-comparison >= (a b rest) b/>=
- "Check whether A is larger or equal to B, B is larger or equal to the
- first element in REST, and so on for all subsequent arguments.
- This will lazily evaluate each value: if A is smaller than B,
- then no subsequent arguments will be evaluated.
- ### Example:
- ```cl
- > (with (a 3)
- . (>= 5 a 1))
- out = true
- ```")
|