feat: allow for multibranches in case (#1276)

This commit is contained in:
Veit Heller 2021-07-08 20:43:48 +02:00 committed by GitHub
parent ca0f9f7d4f
commit 0adc1abd50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 5 deletions

View File

@ -141,6 +141,12 @@ Example:
(defmacro unless [condition form]
(list 'if condition (list) form))
(hidden treat-case-handler)
(defndynamic treat-case-handler [name handler]
(if (and (list? handler) (> (length handler) 1) (= ':or (car handler)))
(cons 'or (map (fn [val] (list '= name val)) (cdr handler)))
(list '= name handler)))
(hidden case-internal)
(defndynamic case-internal [name xs]
(if (= (length xs) 0)
@ -150,24 +156,28 @@ Example:
(if (= (length xs) 1)
(car xs)
(list 'if
(list '= name (car xs))
(treat-case-handler name (car xs))
(cadr xs)
(case-internal name (cddr xs)))))))
(doc case "takes a form and a list of branches which are value and operation
pairs. If a value matches, the operation is executed. It takes a catch-all else
branch that is executed if nothing matches.
pairs. If a value matches (or any in a list of values preced by `:or`), the
operation is executed. It takes a catch-all else branch that is executed if
nothing matches.
Example:
```
(case (+ 10 1)
10 (println* \"nope\")
11 (println* \"yup\")
(:or 12 13) (println* \"multibranch, but nope\")
(println* \"else branch\")
)
```")
(defmacro case [form :rest branches]
(case-internal form branches))
(let [name (gensym)]
(list 'let [name form]
(case-internal name branches))))
(defmodule Dynamic
(doc flip

View File

@ -7,7 +7,7 @@
(doc gensym-with "Generates symbols dynamically, based on a symbol name.")
(defndynamic gensym-with [x]
(do
(set! *gensym-counter* (inc *gensym-counter*))
(set! *gensym-counter* (+ *gensym-counter* 1))
(Symbol.concat [x (Symbol.from *gensym-counter*)])))
(doc gensym "Generates symbols dynamically as needed.")

View File

@ -34,6 +34,12 @@
1 true
false))
(defn test-case-multi []
(case 1
2 false
(:or 1 3) true
false))
(defmacro test-not [a] (not a))
(defmacro test-< [a b] (< a b))
(defmacro test-> [a b] (> a b))
@ -84,6 +90,9 @@
(assert-true test
(test-case-select)
"case correctly selects branch")
(assert-true test
(test-case-multi)
"case correctly selects multibranch")
(assert-true test
(test-comment)
"comment ignores input")