A couple more thoughts...
We could also provide an alternative that isn't stringly-typed:
/* Swift supplies init args by the position in which they are declared */
protocol ExpressibleByCaseIndex {
init( `case`: Int, arguments: Any ... )
}
Maybe that's better in terms of performance, and prevention of typos.
Also, my preference is to allow cases to be usable with, or without their arguments: so we allow both .foo and .foo(123) and let the programmer decide how to handle that in init. If we want to give the programmer the option to allow/forbid this, maybe we could use a new syntax for declaring cases. Eg:
struct Param: ExpressibleByCase {
case
height(Int)?, // accepts .height(123) *or* .height
length(Int) // accepts .length(123) *only*
This would be the missing piece that makes a paradigm for accessing an enum payload (that the introduction of @dynamicCallable made possible), ergonomic.
Everyone has different tastes, but to mine, the struct paradigm is more convenient than Swift enums-with-payload.