I’m designing a custom JSON enum type, something like this:
enum JSON: Equatable {
case string(String)
case number(Float)
case object([String:JSON])
case array([JSON])
case bool(Bool)
case null
}
Initially it was read-only, but now users of the type are requesting writable subscripts and other mutation features. I’m not sure if I should offer only immutable API such as updating(key:to:) -> JSON or removing(key:) -> JSON, or if I should allow in-place mutation. In other languages I would go for the immutable API, but Swift already offers nice opt-in immutability with let vs. var. So should I simply offer a mutable API and let/var users decide? How do people approach this?
infinitives for mutating operations: mutate(), and
participles for copying operations: mutated() (or mutating(argument) if it requires a direct object—appending(x) is less awkward than appended(x)).
Express it as a computed property if it is O(1) and has no arguments; express it as a function if it is more complex. (e.g. Collection’s first vs sorted())
Thank you, in the end I decided to offer both options. (Would it be interesting to have the option to get the non-mutating versions for free? Where something like @someAnnotation mutating shuffle() would also generate a shuffling counterpart that would copy self and apply the mutating method.)
And if you have something like the much-talked with you can do the copying version from the mutating one without writing the boilerplate (or at least the boilerplate becomes calling the function)