Bash/Clj-like "case" #1230
-
What is the most "ergonomic" way to implement (case "hello"
("hi" "Hello" "hello") (println "World")
:true "...") case hello in
hi|Hello|hello)
echo World
;;
*)
...
esac The Bash is just there for completion's sake. I find it rather unsightly, among other shortcomings. I could use In Janet I would write (case "hello"
"hi" (print "World")
"Hello" (print "World")
"hello" (print "World")
"...") or (defn foo [bar]
(case foo
"hi" (print "World")
"Hello" (foo "hi")
"hello" (foo "hi")
"..." but that feels like boiler plate to me. An alternative, and what I'm currently doing, is (defn in? [el coll]
(some (partial = el) coll))
(defn foo [bar]
(cond bar
(in? foo ["hi" "Hello" "hello"] (print "World")
"...")) but that also isn't great. I feel like I'm just using the code equivalent of duck tape, which isn't surprising since I'm nowhere close to being a real programmer. To those of you who actually know a thing or two about Janet (or just programming in general), how would you solve this? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 13 replies
-
I've been outsourcing the behaviour I want to duplicate into a function like so: (defn add [x y] (+ x y))
(defn exec [op & args]
(case op
"add" (add ;args)
"a" (add ;args)
(error "not supported"))) You could of course write your own version of the case macro that works on arrays like so: (defn exec [op & args]
(multi-case op
["add" "a"] (+ ;args)
["substract" "s"] (- ;args)
(error "not supported"))) I don't know if anyone has done that yet. |
Beta Was this translation helpful? Give feedback.
-
The main difficulty is you may want to match on a tuple too. (defn- switch*
[& xs]
(match xs
[k v & rest]
(if (and (tuple? k) (= :parens (tuple/type k)))
[;(interleave k (seq [:repeat (length k)] v))
;(switch* ;rest)]
[k v ;(switch* ;rest)])
[v] [v]
(error "unreachable")))
(defmacro switch
[x & xs]
(let [cases (switch* ;xs)]
~(case ,x
,;cases))) It's an initial attempt and is largely untested, but hey, if it works eh? (each e ["hi" "hallo" "ok" "nope"]
(switch e
("hi" "Hello") (print "A")
("hello" "hallo") (print "B")
"ok" (print "then")
(print "..."))) which seems to work. |
Beta Was this translation helpful? Give feedback.
The main difficulty is you may want to match on a tuple too.
Thankfully,
(= [1] '(1))
, which means we can check againsttuple/type
instead of requiringquote
semantics.Does this work for you?
It's an initial attempt and is largely untested, but hey, if it works eh?
The only testing I've done is: