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


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow