> I feel about them the way I do about switch statements - they're brittle and inextensible.
That is not the case in a language like F# or OCaml. I do note that F# was introduced only slightly before Clojure was, but pattern matching provides nicely extensible functions and are anything but brittle in those languages. Also, active patterns in F# allow one to extend the pattern matching functionality.
> The binding aspect is used to rename structure components because the language throws the names away, presuming the types are enough. Again, redundantly, all over the app, with plenty of opportunity for error.
I'm not sure what he means here. Again in a language like F#, names of the data aren't thrown away. They are pattern matched against, only being "thrown away" to do actual calculations. Nothing is ever lost where the data came from. For example:
type Shape =
| Circle r
| Square s
let area shape =
match shape with
| Circle r -> System.Math.PI * r * r
| Square s -> s * s
There's no confusion here. In fact, pattern matching in a language like F# allows one to completely remove the possibility of error. For example, this really shows off in parsing applications. Once your parsing function returns a type that can be pattern matched, it's extremely difficult to have an error in the pattern matching sections of code. These are typically the most robust parts of the application.> I'd much rather use (defrecord Color [r g b a]) and end up with maps with named parts than do color of
real*real*real*real,
> and have to rename the parts in patterns matches everywhere (was it rgba or argb?)I don't understand this either. In F#:
type Color = { R: float; G: float; B: float }
let colorFunction { R=r; G=g; B=b } = r * g * b
No names are thrown away. Also, the comment on rather using maps seems to assume the data type for every element of the data structure is the same. How do you just use maps when the underlying types of your record aren't the same?