If you just want to define a function in one place, this is pretty idiomatic:
(def reverse (x)
(if alist.x
rev.x
(case type.x
string (string:rev:coerce x 'cons)
(err:+ "Called reverse with " (tostring write.x)))))
If you want to write the different cases in different places in the code, here's the way Anarki (https://github.com/arclanguage/anarki) currently defines `rev`:
; in arc.arc
(def rev (xs)
"Returns a list containing the elements of 'xs' back to front."
(loop (xs xs acc nil)
(if (no xs)
acc
(recur cdr.xs
(cons car.xs acc)))))
; in lib/strings.arc
(defextend rev (x) (isa x 'string)
(as string (rev:as cons x)))
The community has made several little definition utilities for doing predicate dispatch in Arc, and `defextend` is a good example of those, so it's pretty idiomatic.