| A list of design patterns for a language amounts to a list of weaknesses in the language or in its library. If the pattern could be captured in a library, that pattern would just be using the library. If the core language provided the feature, the pattern would just amount to using the feature. Generally it is better to improve the language to the point where the feature can be added as a library component, but sometimes that is too hard. Thus, for most languages nowadays a "dictionary" type is provided in the core language, because a useful hash table library cannot be written with language primitives. In C, hash tables are open-coded again in each place where one is needed, because the language provides neither the feature, nor facilities sufficient to capture it in a library. Rust is powerful and expressive enough that hash tables are library components. Conversely, pattern matching and coroutines are built into Rust. It should never be forgotten that (1) this was because the language was not expressive enough to capture the features satisfactorily in a library; and that (2) it would be better if, someday, the core feature became unnecessary because the language became expressive enough provide it as a library. One reason it is better for features to be provided in a library is that another library can implement a variation on the feature that might not be as widely useful as the core version, but is better tuned to a less-common but still important use. Another is that users can invent whole new features by combining powerful primitives that the language designers would not have time, or possibly inclination, to implement themselves. Thus, in a certain sense, all patterns are anti-patterns. |