2 Diving In
2.5 Pattern Matching
2.5.1 What Are Patterns?
Pattern matching in Erlang is huge, and it has a proportional impact on LFE and
what one can do with this dialect of Lisp. Pattern matching in LFE can be used
in function clauses,
receive and in the macros
bc. From the REPL, pattern matching may be done
set as well.
Pattern matching in LFE happens when an expression matches a given pattern, e.g.:
<pattern> might be something like this:
<expression> is any legal LFE expression. Ideally, it will return
data that will be matched by the pattern.
If the matching succeeds, any unbound variables in the pattern become bound. If the matching fails, a run-time error occurs. All of this is best understood through the examples given below. Each example is preceeded by the general form of pattern as used in the given context. This should help keep things clear, even when the examples get convoluted.
2.5.2 Patterns in Forms
Pattern matching in
let has the following general form:
In this example, we have a pattern of
(tuple len status data) and this is
getting matched against our expression which is some data of the form
#(8 ok "Trillian"). The pattern expects a tuple, and a tuple is what we
gave it. With the pattern's variables bound inside the
let, we can return
a list of the variables.
If our pattern was written to expect a list and the expression was a tuple,
we'd get a
Whatever our expression is going to be needs to be matched in the pattern. If
we had a list integers in the expression, we would need a pattern like
(list i1 i2 i3 ...).
Here's a super-simplified version of a
let with pattern matching:
Here our pattern was simply the variable
data and our expression was the
string "Trillian". This, of course, is easily recognized as a standard variable
assignment within a
Patterns can nest, though, and with this you can start to get a sense of the power they hold. Let's look at a more complicated example:
As you can see, we've nested our expression: length is a two-valued list and status is a two-valued tuple. Our pattern, however, is still simple. But this is going to change: we want to extract our data into more variables, and we do this by mirroring the expression data structure in the pattern itself:
As you can see, our nested pattern extracted the data into the pattern's variables. If all we cared about was the status message, we could make this simpler by using the "I don't care" variable (the underscore):
Having seen these examples, you are probably gaining some insight into the power of pattern matching in Erlang and LFE. There's more, though :-) See below for equally potent uses.
Pattern matching in
case has the following general form:
Keep in mind that
case may also be used (optionally) inside the
form. For more information on
Let's take a look at
case in action:
The patterns we are using in this
case example expect data of one
particular format, differentiating by the second element of the provided tuple.
With new data, we can exercise the other cases:
We won't re-type the
case example here; just hit the "up" arror until you
get to the
case entry and hit return:
Similarly, we can test the remaining case:
Pattern matching in
receive has the following general form:
There is a tutorial on working with Erlang's light weight processes in LFE, and
several example usages of
receive are given there. On the second page of
that tutorial, we see that any message sent to
receive is accepted and
processed. In the example below, we replace the simple pattern of the whole
msg) with a series of patterns that will print only if the
message matches one of the provided patterns.
Save the following in a file named
Next, start up the LFE REPL, compile the module above, and start our safety server:
Now let's give our patterns a try by sending messages to the server process:
As you can see, the
receive patterns are working.
We can also see what happens when we send messages that don't match any of the defined patterns:
Absolutely nothing, that's what. Well, nothing from the process we spawned, that is... just the REPL doing its thang.
Pattern matching in
cond has the following general form:
cond looks like this:
In other words, a series of tests with conditional results. LFE extends the basic form with support for pattern matching, as seen in the general form above.
Here's an example of how one can do pattern matching in LFE with
(starting with the setting of some data):
Note that this is a replacement of the
case example above.
We can set the
data variable differently to exercise the other code
paths, and then enter the
cond expression from above (elided below to
2.5.3 Special Cases
set in the REPL
set in the REPL has the following general form:
set is only valid when running the LFE shell. Example usage:
188.8.131.52 Aliases with
Aliases are defined with the following general form:
Aliases can be used anywhere in a pattern. A quick example of this, updating the previous example with aliases:
The same variables that were bound in the previous example are bound in this one:
In addition, however, we have aliased new variables to these:
184.108.40.206 Arguments to
Pattern matching in functions has the following general form:
We haven't covered functions yet (that's coming up in Chapter 4), so this will be a short preview focusing just on the pattern usage in functions, with more detail coming later.
Proper functions can't be defined in the LFE REPL, so save the following to
As you can see, the usual function arguments have been replaced with a pattern.
In particular, this function will accept any of three options with two
arguments each: where the first argument is
'ok, or where it is
'warn, or where it is
Let's compile our new module from the LFE REPL:
Now let's step it through its paces:
If a pattern is not matched in our example (which has no fallback pattern), an error is raised:
220.127.116.11 Arguments to Anonymous Functions
One can use patterns in arguments with anonymous functions similarly to how one
does with named functions, demonstrated above. In LFE, this is done with
match-lambda. Here's an example done in the REPL:
Usage is similar as well:
18.104.22.168 Patterns in Comprehensions
List and binary comprehensions make use of patterns in a limited sense. They have the following general forms:
guard in both cases is optional.
You can read more about LFE comprehensions in section 3.3