Elixir Language
La coincidencia de patrones
Buscar..
Funciones de coincidencia de patrones
#You can use pattern matching to run different
#functions based on which parameters you pass
#This example uses pattern matching to start,
#run, and end a recursive function
defmodule Counter do
def count_to do
count_to(100, 0) #No argument, init with 100
end
def count_to(counter) do
count_to(counter, 0) #Initialize the recursive function
end
def count_to(counter, value) when value == counter do
#This guard clause allows me to check my arguments against
#expressions. This ends the recursion when the value matches
#the number I am counting to.
:ok
end
def count_to(counter, value) do
#Actually do the counting
IO.puts value
count_to(counter, value + 1)
end
end
Patrón de coincidencia en un mapa
%{username: username} = %{username: "John Doe", id: 1} # username == "John Doe"
%{username: username, id: 2} = %{username: "John Doe", id: 1} ** (MatchError) no match of right hand side value: %{id: 1, username: "John Doe"}
Coincidencia de patrones en una lista
También puede hacer un patrón de coincidencia en las estructuras de datos de Elixir, como las listas.
Liza
Coincidencia en una lista es bastante simple.
[head | tail] = [1,2,3,4,5] # head == 1 # tail == [2,3,4,5]
Esto funciona al hacer coincidir los primeros (o más) elementos de la lista con el lado izquierdo de la |
(tubería) y el resto de la lista a la derecha de la variable |
.
También podemos coincidir en valores específicos de una lista:
[1,2 | tail] = [1,2,3,4,5] # tail = [3,4,5] [4 | tail] = [1,2,3,4,5] ** (MatchError) no match of right hand side value: [1, 2, 3, 4, 5]
Enlace de múltiples valores consecutivos a la izquierda de la |
También está permitido:
[a, b | tail] = [1,2,3,4,5]
# a == 1
# b == 2
# tail = [3,4,5]
Más complejo aún: podemos hacer coincidir un valor específico y compararlo con una variable:
iex(11)> [a = 1 | tail] = [1,2,3,4,5] # a == 1
Obtén la suma de una lista usando la coincidencia de patrones
defmodule Math do
# We start of by passing the sum/1 function a list of numbers.
def sum(numbers) do
do_sum(numbers, 0)
end
# Recurse over the list when it contains at least one element.
# We break the list up into two parts:
# head: the first element of the list
# tail: a list of all elements except the head
# Every time this function is executed it makes the list of numbers
# one element smaller until it is empty.
defp do_sum([head|tail], acc) do
do_sum(tail, head + acc)
end
# When we have reached the end of the list, return the accumulated sum
defp do_sum([], acc), do: acc
end
Funciones anonimas
f = fn
{:a, :b} -> IO.puts "Tuple {:a, :b}"
[] -> IO.puts "Empty list"
end
f.({:a, :b}) # Tuple {:a, :b}
f.([]) # Empty list
Tuplas
{ a, b, c } = { "Hello", "World", "!" }
IO.puts a # Hello
IO.puts b # World
IO.puts c # !
# Tuples of different size won't match:
{ a, b, c } = { "Hello", "World" } # (MatchError) no match of right hand side value: { "Hello", "World" }
Leyendo un archivo
La coincidencia de patrones es útil para una operación como la lectura de archivos que devuelve una tupla.
Si el archivo sample.txt
contiene This is a sample text
, entonces:
{ :ok, file } = File.read("sample.txt")
# => {:ok, "This is a sample text"}
file
# => "This is a sample text"
De lo contrario, si el archivo no existe:
{ :ok, file } = File.read("sample.txt")
# => ** (MatchError) no match of right hand side value: {:error, :enoent}
{ :error, msg } = File.read("sample.txt")
# => {:error, :enoent}
Funciones anónimas que coinciden con el patrón
fizzbuzz = fn (0, 0, _) -> "FizzBuzz" (0, _, _) -> "Fizz" (_, 0, _) -> "Buzz" (_, _, x) -> x end my_function = fn(n) -> fizzbuzz.(rem(n, 3), rem(n, 5), n) end