Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is the preferred method for writing "guards"?

Tags:

haskell

I’ve created a function in which I can use (as far as I know) case expressions or guards.

foo a b c = case a of 1 -> [...]
                      2 -> [...]
                      3 -> [...] 
                      [...]
                      otherwise -> error "..."

or

foo a b c | a == 1 = [...]
          | a == 2 = [...]
          | a == 3 = [...] 
          | [...]
          | otherwise = error "..."

So, the question is: which of those 2 (case or guards) are “better” coding? Are both basically the same?

like image 925
Nomics Avatar asked Dec 10 '11 23:12

Nomics


People also ask

What is guard expression?

In computer programming, a guard is a boolean expression that must evaluate to true if the program execution is to continue in the branch in question.

What are guards in Elixir?

Guards are a way to augment pattern matching with more complex checks. They are allowed in a predefined set of constructs where pattern matching is allowed. Not all expressions are allowed in guard clauses, but only a handful of them.

What is guard clause in Javascript?

What Are Guard Clauses? A guard clause is simply a single piece of conditional logic at the beginning of a function which will return from the function early if a certain condition is met.


2 Answers

The first one is considered better style, for 2 reasons.

First of all: Many people would say that it looks better, since you don't have to type out all of the ==. This is a very subjective reason, of course. Also, you would normally not even introduce a new case statement, but just match the arguments in the function argument list like so:

foo 1 b c = ... -- etc
...
foo _ b c = ... -- for the "otherwise" part

This makes the code even more compact and readable, which many people like.

Secondly, there actually is a semantic difference. Imagine that you have a data type like this:

data Cake = Apple | Cheese | Cream

If you use the first method, you match against the constructors in the case..of expression:

case a of
  Apple -> "fruit"
  _     -> "not fruit"

However, if you try to do a guarded expression of some sort, like this:

| a == Apple = "fruit"
| otherwise  = "not fruit"

... it won't actually work, because the Cake type doesn't have an Eq instance, so you can't use == to compare two values. Introducing an Eq instance (with deriving (Eq) after the data definition) is not always wanted, so not having to do it in this case might be significant.

like image 82
dflemstr Avatar answered Oct 20 '22 00:10

dflemstr


When a guard can be rewritten as a (guardless) case-statement on one of the parameters, it's not actual necessary. I.e. you can just write it as:

foo 1 b c = [...]
foo 2 b c = [...]
foo 3 b c = [...]
[...]

Which is the preferred way to write it. You'd use guards when the condition you want can't be expressed as a pattern. And you'd use a case-statement when you need to match on something other than one of the parameters.

like image 35
sepp2k Avatar answered Oct 20 '22 00:10

sepp2k