3/8/2016
case, cond and if - Elixir
HOME
INSTALL
GETTING STARTED
LEARNING
DOCS
BLOG
PACKAGES
News: Elixir v1.2 released
case, cond and if
Search...
1 case
2 Expressions in guard clauses
G ETTI N G ST A RTED
3 cond
1. Introduction
4 if and unless
2. Basic types
5 do/end blocks
3. Basic operators
4. Pattern matching
In this chapter, we will learn about the case, cond and if control-flow
5. case, cond and if
structures.
6. Binaries, strings and char
case
case allows us to compare a value against many patterns until we find a
matching one:
lists
7. Keywords and maps
8. Modules
9. Recursion
10. Enumerables and streams
iex> case {1, 2, 3} do
...>
{4, 5, 6} ->
...>
...>
"This clause won't match"
{1, x, 3} ->
...>
"This clause will match and bind x to 2 in this
clause"
...>
_ ->
...>
"This clause would match any value"
...> end
"This clause will match and bind x to 2 in this clause"
11. Processes
12. IO and the file system
13. alias, require and import
14. Module attributes
15. Structs
16. Protocols
17. Comprehensions
18. Sigils
If you want to pattern match against an existing variable, you need to use the ^
operator:
19. try, catch and rescue
20. Typespecs and behaviours
21. Erlang libraries
iex> x = 1
22. Where to go next
1
iex> case 10 do
...>
^x -> "Won't match"
...>
_ -> "Will match"
M IX A N D OTP
...> end
1. Introduction to Mix
"Will match"
2. Agent
[Link]
1/7
3/8/2016
case, cond and if - Elixir
3. GenServer
Clauses also allow extra conditions to be specified via guards:
4. Supervisor and Application
5. ETS
iex> case {1, 2, 3} do
...>
{1, x, 3} when x > 0 ->
...>
...>
"Will match"
_ ->
...>
"Would match, if guard condition were not satisfied"
...> end
"Will match"
6. Dependencies and umbrella
apps
7. Task and gen-tcp
8. Docs, tests and with
9. Distributed tasks and
configuration
The first clause above will only match when x is positive.
M ETA -PROG RA M MI N G I N
EL IX I R
Expressions in guard clauses
1. Quote and unquote
Elixir imports and allows the following expressions in guards by default:
2. Macros
3. Domain Specific Languages
comparison operators ( ==, !=, ===, !==, >, >=, <, <=)
boolean operators ( and, or, not)
S PON SORS
arithmetic operations ( +, -, *, /)
arithmetic unary operators ( +, -)
the binary concatenation operator <>
the in operator as long as the right side is a range or a list
all the following type check functions:
is_atom/1
is_binary/1
is_bitstring/1
EL IX I R RA D AR
A weekly Elixir email newsletter
with content curated by
Plataformatec. Subscribe
below.
is_boolean/1
is_float/1
is_function/1
is_function/2
Elixir
Radar
weekly
Subscribe
now
newsletter
is_integer/1
is_list/1
is_map/1
is_nil/1
is_number/1
is_pid/1
is_port/1
[Link]
2/7
3/8/2016
case, cond and if - Elixir
is_reference/1
is_tuple/1
plus these functions:
abs(number)
binary_part(binary, start, length)
bit_size(bitstring)
byte_size(bitstring)
div(integer, integer)
elem(tuple, n)
hd(list)
length(list)
map_size(map)
node()
node(pid | ref | port)
rem(integer, integer)
round(number)
self()
tl(list)
trunc(number)
tuple_size(tuple)
Additionally, users may define their own guards. For example, the Bitwise
module defines guards as functions and operators: bnot, ~~~, band, &&&,
bor, |||, bxor, ^^^, bsl, <<<, bsr, >>>.
Note that while boolean operators such as and, or, not are allowed in
guards, the more general and short-circuiting operators &&, || and ! are
not.
Keep in mind errors in guards do not leak but simply make the guard fail:
iex> hd(1)
** (ArgumentError) argument error
:[Link](1)
iex> case 1 do
...>
x when hd(x) -> "Won't match"
...>
x -> "Got: #{x}"
...> end
"Got 1"
[Link]
3/7
3/8/2016
case, cond and if - Elixir
If none of the clauses match, an error is raised:
iex> case :ok do
...>
:error -> "Won't match"
...> end
** (CaseClauseError) no case clause matching: :ok
Note anonymous functions can also have multiple clauses and guards:
iex> f = fn
...>
x, y when x > 0 -> x + y
...>
x, y -> x * y
...> end
#Function<12.71889879/2 in :erl_eval.expr/5>
iex> f.(1, 3)
4
iex> f.(-1, 3)
-3
The number of arguments in each anonymous function clause needs to be the
same, otherwise an error is raised.
cond
case is useful when you need to match against different values. However, in
many circumstances, we want to check different conditions and find the first
one that evaluates to true. In such cases, one may use cond:
iex> cond do
...>
2 + 2 == 5 ->
...>
...>
"This will not be true"
2 * 2 == 3 ->
...>
...>
"Nor this"
1 + 1 == 2 ->
...>
"But this will"
...> end
"But this will"
This is equivalent to else if clauses in many imperative languages (although
used way less frequently here).
If none of the conditions return true, an error is raised. For this reason, it may
be necessary to add a final condition, equal to true, which will always match:
[Link]
4/7
3/8/2016
case, cond and if - Elixir
iex> cond do
...>
2 + 2 == 5 ->
...>
...>
"This is never true"
2 * 2 == 3 ->
...>
...>
"Nor this"
true ->
...>
"This is always true (equivalent to else)"
...> end
"This is always true (equivalent to else)"
Finally, note cond considers any value besides nil and false to be true:
iex> cond do
...>
hd([1,2,3]) ->
...>
"1 is considered as true"
...> end
"1 is considered as true"
if and unless
Besides case and cond, Elixir also provides the macros if/2 and unless/2
which are useful when you need to check for just one condition:
iex> if true do
...>
"This works!"
...> end
"This works!"
iex> unless true do
...>
"This will never be seen"
...> end
nil
If the condition given to if/2 returns false or nil, the body given between
do/end is not executed and it simply returns nil. The opposite happens with
unless/2.
They also support else blocks:
iex> if nil do
...>
"This won't be seen"
...> else
...>
"This will"
...> end
"This will"
[Link]
5/7
3/8/2016
case, cond and if - Elixir
Note:Aninterestingnoteregarding if/2and unless/2isthat
theyareimplementedasmacrosinthelanguagetheyarent
speciallanguageconstructsastheywouldbeinmany
[Link]
if/2inthe [Link] Kernelmoduleisalso
whereoperatorslike +/2andfunctionslike is_function/2are
defined,allautomaticallyimportedandavailableinyourcode
bydefault.
do/end blocks
At this point, we have learned four control structures: case, cond, if and
unless, and they were all wrapped in do/end blocks. It happens we could also
write if as follows:
iex> if true, do: 1 + 2
3
Notice how the example above has a comma between true and do:, thats
because it is using Elixirs regular syntax where each argument is separated by
comma. We say this syntax is using keywordlists. We can pass else using
keywords too:
iex> if false, do: :this, else: :that
:that
do/end blocks are a syntactic convenience built on top of the keywords one.
Thats why do/end blocks do not require a comma between the previous
argument and the block. They are useful exactly because they remove the
verbosity when writing blocks of code. These are equivalent:
iex> if true do
...>
a=1+2
...>
a + 10
...> end
13
iex> if true, do: (
...>
a=1+2
...>
a + 10
...> )
13
[Link]
6/7
3/8/2016
case, cond and if - Elixir
One thing to keep in mind when using do/end blocks is they are always bound
to the outermost function call. For example, the following expression:
iex> is_number if true do
...> 1 + 2
...> end
** (RuntimeError) undefined function: if/1
Would be parsed as:
iex> is_number(if true) do
...> 1 + 2
...> end
** (RuntimeError) undefined function: if/1
Which leads to an undefined function error as Elixir attempts to invoke if/1.
Adding explicit parentheses is enough to resolve the ambiguity:
iex> is_number(if true do
...> 1 + 2
...> end)
true
Keyword lists play an important role in the language and are quite common in
many functions and macros. We will explore them a bit more in a future
chapter. Now it is time to talk about Binaries, strings and char lists.
Previous
Top
Next
2012-2016 Plataformatec. All rights reserved.
[Link]
7/7