mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2025-08-05 06:17:36 +02:00
Added one more example with guards, fixed typos and identation.
This commit is contained in:
@@ -141,33 +141,33 @@ number < atom < reference < functions < port < pid < tuple < list < bit string
|
|||||||
|
|
||||||
# `if` expression
|
# `if` expression
|
||||||
if false do
|
if false do
|
||||||
"This will never be seen"
|
"This will never be seen"
|
||||||
else
|
else
|
||||||
"This will"
|
"This will"
|
||||||
end
|
end
|
||||||
|
|
||||||
# There's also `unless`
|
# There's also `unless`
|
||||||
unless true do
|
unless true do
|
||||||
"This will never be seen"
|
"This will never be seen"
|
||||||
else
|
else
|
||||||
"This will"
|
"This will"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Remember pattern matching? Many control-flow structures in elixir rely on it.
|
# Remember pattern matching? Many control-flow structures in elixir rely on it.
|
||||||
|
|
||||||
# `case` allows us to compare a value against many patterns:
|
# `case` allows us to compare a value against many patterns:
|
||||||
case {:one, :two} do
|
case {:one, :two} do
|
||||||
{:four, :five} ->
|
{:four, :five} ->
|
||||||
"This won't match"
|
"This won't match"
|
||||||
{:one, x} ->
|
{:one, x} ->
|
||||||
"This will match and assign `x` to `:two`"
|
"This will match and assign `x` to `:two`"
|
||||||
_ ->
|
_ ->
|
||||||
"This will match any value"
|
"This will match any value"
|
||||||
end
|
end
|
||||||
|
|
||||||
# It's common practive to assign a value to `_` if we don't need it.
|
# It's common practive to assign a value to `_` if we don't need it.
|
||||||
# For example, if only the head of a list matters to us:
|
# For example, if only the head of a list matters to us:
|
||||||
[head | _] = [1,2,3]
|
[head | _] = [1,2,3]
|
||||||
head #=> 1
|
head #=> 1
|
||||||
|
|
||||||
# For better readability we can do the following:
|
# For better readability we can do the following:
|
||||||
@@ -177,35 +177,35 @@ head #=> :a
|
|||||||
# `cond` lets us check for many conditions at the same time.
|
# `cond` lets us check for many conditions at the same time.
|
||||||
# Use `cond` instead of nesting many `if` expressions.
|
# Use `cond` instead of nesting many `if` expressions.
|
||||||
cond do
|
cond do
|
||||||
1 + 1 == 3 ->
|
1 + 1 == 3 ->
|
||||||
"I will never be seen"
|
"I will never be seen"
|
||||||
2 * 5 == 12 ->
|
2 * 5 == 12 ->
|
||||||
"Me neither"
|
"Me neither"
|
||||||
1 + 2 == 3 ->
|
1 + 2 == 3 ->
|
||||||
"But I will"
|
"But I will"
|
||||||
end
|
end
|
||||||
|
|
||||||
# It is common to see a last condition equal to `true`, which will always match.
|
# It is common to see a last condition equal to `true`, which will always match.
|
||||||
cond do
|
cond do
|
||||||
1 + 1 == 3 ->
|
1 + 1 == 3 ->
|
||||||
"I will never be seen"
|
"I will never be seen"
|
||||||
2 * 5 == 12 ->
|
2 * 5 == 12 ->
|
||||||
"Me neither"
|
"Me neither"
|
||||||
true ->
|
true ->
|
||||||
"But I will (this is essentially an else)"
|
"But I will (this is essentially an else)"
|
||||||
end
|
end
|
||||||
|
|
||||||
# `try/catch` is used to catch values that are thrown, it also supports an
|
# `try/catch` is used to catch values that are thrown, it also supports an
|
||||||
# `after` clause that is invoked whether or not a value is catched.
|
# `after` clause that is invoked whether or not a value is catched.
|
||||||
try do
|
try do
|
||||||
throw(:hello)
|
throw(:hello)
|
||||||
catch
|
catch
|
||||||
message -> "Got #{message}."
|
message -> "Got #{message}."
|
||||||
after
|
after
|
||||||
IO.puts("I'm the after clause.")
|
IO.puts("I'm the after clause.")
|
||||||
end
|
end
|
||||||
#=> I'm the after clause
|
#=> I'm the after clause
|
||||||
# "Got :hello"
|
# "Got :hello"
|
||||||
|
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
## -- Modules and Functions
|
## -- Modules and Functions
|
||||||
@@ -218,8 +218,8 @@ square.(5) #=> 25
|
|||||||
# They also accept many clauses and guards. Guards let you fine tune pattern matching,
|
# They also accept many clauses and guards. Guards let you fine tune pattern matching,
|
||||||
# they are indicated by the `when` keyword:
|
# they are indicated by the `when` keyword:
|
||||||
f = fn
|
f = fn
|
||||||
x, y when x > 0 -> x + y
|
x, y when x > 0 -> x + y
|
||||||
x, y -> x * y
|
x, y -> x * y
|
||||||
end
|
end
|
||||||
|
|
||||||
f.(1, 3) #=> 4
|
f.(1, 3) #=> 4
|
||||||
@@ -234,32 +234,32 @@ elem({1,2,3}, 0) #=> 1
|
|||||||
# You can group several functions into a module. Inside a module use `def`
|
# You can group several functions into a module. Inside a module use `def`
|
||||||
# to define your functions.
|
# to define your functions.
|
||||||
defmodule Math do
|
defmodule Math do
|
||||||
def sum(a, b) do
|
def sum(a, b) do
|
||||||
a + b
|
a + b
|
||||||
end
|
end
|
||||||
|
|
||||||
def square(x) do
|
def square(x) do
|
||||||
x * x
|
x * x
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Math.sum(1, 2) #=> 3
|
Math.sum(1, 2) #=> 3
|
||||||
Match.square(3) #=> 9
|
Match.square(3) #=> 9
|
||||||
|
|
||||||
# To compile our little Math module save it as `math.ex` and use `elixirc`
|
# To compile our simple Math module save it as `math.ex` and use `elixirc`
|
||||||
elixirc math.ex
|
# in your terminal: elixirc math.ex
|
||||||
|
|
||||||
# Inside a module we can define functions with `def` and private functions with `defp`.
|
# Inside a module we can define functions with `def` and private functions with `defp`.
|
||||||
# A function defined with `def` is available to be invoked from other modules,
|
# A function defined with `def` is available to be invoked from other modules,
|
||||||
# a private function can only be invoked locally.
|
# a private function can only be invoked locally.
|
||||||
defmodule PrivateMath do
|
defmodule PrivateMath do
|
||||||
def sum(a, b) do
|
def sum(a, b) do
|
||||||
do_sum(a, b)
|
do_sum(a, b)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_sum(a, b) do
|
defp do_sum(a, b) do
|
||||||
a + b
|
a + b
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
PrivateMath.sum(1, 2) #=> 3
|
PrivateMath.sum(1, 2) #=> 3
|
||||||
@@ -267,27 +267,29 @@ PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
|
|||||||
|
|
||||||
# Function declarations also support guards and multiple clauses:
|
# Function declarations also support guards and multiple clauses:
|
||||||
defmodule Geometry do
|
defmodule Geometry do
|
||||||
def area({:rectangle, w, h}) do
|
def area({:rectangle, w, h}) do
|
||||||
w * h
|
w * h
|
||||||
end
|
end
|
||||||
|
|
||||||
def area({:circle, r}) when is_number(r) do
|
def area({:circle, r}) when is_number(r) do
|
||||||
3.14 * r * r
|
3.14 * r * r
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Geometry.area({:rectangle, 2, 3}) #=> 6
|
Geometry.area({:rectangle, 2, 3}) #=> 6
|
||||||
Geometry.area({:circle, 3}) #=> 28.25999999999999801048
|
Geometry.area({:circle, 3}) #=> 28.25999999999999801048
|
||||||
|
Geometry.area({:circle, "not_a_number"})
|
||||||
|
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
|
||||||
|
|
||||||
# Due to immutability, recursion is a big part of elixir
|
# Due to immutability, recursion is a big part of elixir
|
||||||
defmodule Recursion do
|
defmodule Recursion do
|
||||||
def sum_list([head | tail], acc) do
|
def sum_list([head | tail], acc) do
|
||||||
sum_list(tail, acc + head)
|
sum_list(tail, acc + head)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sum_list([], acc) do
|
def sum_list([], acc) do
|
||||||
acc
|
acc
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Recursion.sum_list([1,2,3], 0) #=> 6
|
Recursion.sum_list([1,2,3], 0) #=> 6
|
||||||
@@ -295,12 +297,12 @@ Recursion.sum_list([1,2,3], 0) #=> 6
|
|||||||
# Elixir modules support attributes, there are built-in attributes and you
|
# Elixir modules support attributes, there are built-in attributes and you
|
||||||
# may also add custom attributes.
|
# may also add custom attributes.
|
||||||
defmodule MyMod do
|
defmodule MyMod do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
This is a built-in attribute on a example module.
|
This is a built-in attribute on a example module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@my_data 100 # This is a custom attribute.
|
@my_data 100 # This is a custom attribute.
|
||||||
IO.inspect(@my_data) #=> 100
|
IO.inspect(@my_data) #=> 100
|
||||||
end
|
end
|
||||||
|
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
@@ -322,18 +324,18 @@ joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180]
|
|||||||
|
|
||||||
# The `try` block with the `rescue` keyword is used to handle exceptions
|
# The `try` block with the `rescue` keyword is used to handle exceptions
|
||||||
try do
|
try do
|
||||||
raise "some error"
|
raise "some error"
|
||||||
rescue
|
rescue
|
||||||
RuntimeError -> "rescued a runtime error"
|
RuntimeError -> "rescued a runtime error"
|
||||||
_error -> "this will rescue any error"
|
_error -> "this will rescue any error"
|
||||||
end
|
end
|
||||||
|
|
||||||
# All exceptions have a message
|
# All exceptions have a message
|
||||||
try do
|
try do
|
||||||
raise "some error"
|
raise "some error"
|
||||||
rescue
|
rescue
|
||||||
x in [RuntimeError] ->
|
x in [RuntimeError] ->
|
||||||
x.message
|
x.message
|
||||||
end
|
end
|
||||||
|
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
@@ -354,16 +356,16 @@ spawn(f) #=> #PID<0.40.0>
|
|||||||
# For all of this to be useful we need to be able to receive messages. This is
|
# For all of this to be useful we need to be able to receive messages. This is
|
||||||
# achived with the `receive` mechanism:
|
# achived with the `receive` mechanism:
|
||||||
defmodule Geometry do
|
defmodule Geometry do
|
||||||
def area_loop do
|
def area_loop do
|
||||||
receive do
|
receive do
|
||||||
{:rectangle, w, h} ->
|
{:rectangle, w, h} ->
|
||||||
IO.puts("Area = #{w * h}")
|
IO.puts("Area = #{w * h}")
|
||||||
area_loop()
|
area_loop()
|
||||||
{:circle, r} ->
|
{:circle, r} ->
|
||||||
IO.puts("Area = #{3.14 * r * r}")
|
IO.puts("Area = #{3.14 * r * r}")
|
||||||
area_loop()
|
area_loop()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Compile the module and create a process that evaluates `area_loop` in the shell
|
# Compile the module and create a process that evaluates `area_loop` in the shell
|
||||||
|
Reference in New Issue
Block a user