I almost never use (coerce param 'sym) when I can say sym.param instead. I've always thought Arc doesn't really do enough with the `coerce` function to justify having it in the language; individual functions like `sym` and `string` already do its job more concisely.
In practice when I used to write weakly typed utilities in Arc, I tended to find `zap` very nice:
If you're unfamiliar with `zap`, (zap sym param) is essentially (= param (sym param)).
I prefer strong typing these days, but I've sometimes thought this `zap` technique could be refined to put the coercions in the argument list directly. Arc has (o arg default) for optional arguments, and we could imagine a similar (z coercion arg) for automatically zapping an argument as it comes in:
Something else that's been on my mind is that it could be useful to have higher-order coercion combinators.
Racket code can use `->` to build a contract for a function out of contracts for its arguments and its result. The result of (-> string? string? symbol?) is a contract that verifies a value is a two-argument function and then replaces it with a function that delegates to that one, but which verifies that the arguments are strings and that the result is a symbol.
The same thing could be done for coercions: The result of (as-> string string sym) could be a coercion function that coerces its argument into a two-argument function that delegates to the original value, but which first coerces the arguments to strings and then coerces the result to a symbol.
Similarly, in Racket, `(listof symbol?)` is a contract that checks that a value is a list of symbols, and for coercions we could imagine a corresponding `(aslistof sym)` operation for use in your `(map [coerce _ 'sym] ...)` example.
Sometimes Arc's weak typing suffers from making poor guesses as to whether `nil` is intended as a symbol or as a list (not to mention as a boolean), and it takes some adjusting to work around it: