;; conditionals.lq ;; OR, AND, COND, CASE, etc (define (not x) (if x #f #t)) (define (and *exprs...) (let ((exprs (delayed-expr *exprs...))) (if (empty? exprs) #t (let ((result (eval-in (head exprs) *exprs...))) (if result (if (empty? (tail exprs)) result (apply-in and (tail exprs) *exprs...)) #f))))) (define (or *exprs...) (let ((exprs (delayed-expr *exprs...))) (if (empty? exprs) #f (let ((result (eval-in (head exprs) *exprs...))) (if result result (apply-in or (tail exprs) *exprs...)))))) ;; WHEN/UNLESS: don't fly yet because we cannot call BEGIN as a function... (define (when cond *exprs...) (if cond ;(apply-in begin (delayed-expr *exprs...) *exprs...) (eval-in (pair 'begin (delayed-expr *exprs...)) *exprs...) #f)) (define (unless cond *exprs...) (if cond #f ;(apply-in begin (delayed-expr *exprs...) *exprs...))) (eval-in (pair 'begin (delayed-expr *exprs...)) *exprs...))) (define (cond *body...) (let ((body (delayed-expr *body...))) (if (empty? body) #f (let# (cond1 clause) (head body) ;; destructuring-bind, sort of (if (eval-in cond1 *body...) (eval-in clause *body...) (apply-in cond (tail body) *body...)))))) ;; NOTE: unlike Scheme's CASE, this variant evaluates the list of possible ;; values, so we can put arbitrary expressions in there. (define (case expr *clauses...) (let ((clauses (delayed-expr *clauses...))) (if (empty? clauses) #f (let# (values clause) (head clauses) (let ((value-list (eval-in values *clauses...))) (if (or (equal? value-list #t) (member? expr value-list equal?)) (eval-in clause *clauses...) (apply-in case (pair expr (tail clauses)) *clauses...)))))))