Actually, they are fundamentally different! At least in Haskell, anyway.
Guards are simpler and more flexible: they are essentially just special syntax that translates into a series of if / then expressions. You can put arbitrary Boolean expressions into guards, but they do nothing that you could not do with regular if .
Pattern matches perform several additional actions: they are the only way to deconstruct data , and they bind identifiers within their area . In the same sense that guards are equivalent to if , pattern matching is equivalent to case . Declarations (either at the top level or in the form of a let expression) are also a form of template matching, while the “usual” definitions coincide with a trivial template, one identifier.
Comparison of templates is also usually the main way that Haskell actually does - trying to deconstruct data in a template is one of the few things that makes you appreciate.
By the way, you can actually match patterns in top-level ads:
square = (^2) (one:four:nine:_) = map square [1..]
This is sometimes useful for a group of related definitions.
The GHC also provides a ViewPatterns extension that combines both; you can use arbitrary functions in the context of the binding, and then match the result by result. Of course, it's still just syntactic sugar for ordinary things.
Regarding the daily issue, due to which you can use somewhere a few rough guides:
Definitely use pattern matching for anything that can be paired directly with one or two constructors in depth, where you really don't need complex data in general, but take care of most of the structure. The @ syntax allows you to bind the general structure to a variable, as well as matching patterns on it, but there is too much of what can be ugly and unreadable in one template quickly.
Definitely use protective equipment when you need to make a choice based on some property that does not fit neatly into the template, for example. comparing two Int values to see which is larger.
If you need only a few pieces of data from the depths of a large structure, especially if you also need to use the structure as a whole, the security and access functions are generally more readable than some monstrous template full of @ and _ .
If you need to do the same for values represented by different patterns, but with a convenient predicate for classifying them, using one common pattern with protection is usually more readable. Please note that if the set of guards is not exhaustive, everything that does not work, all defenders will fall to the next pattern (if any). That way, you can combine a common template with some kind of filter to catch exceptional cases, and then match the templates in everything else to get the information you care about.
Definitely do not use protective devices for things that can be trivially checked with a pattern. Checking empty lists is a classic example; use a matching pattern for this.
In general, if in doubt, just stick to the default template, it is usually nicer. If the template starts to get really ugly or confusing, stop to consider how else you could write it. In addition to using protective devices, other options include extracting subexpressions as separate functions or placing case expressions inside the function body to push some of the templates to them and from the main definition.
CA McCann Nov 11 2018-10-11 16:44
source share