jueves, 16 de marzo de 2017

Empezando con Elixir 2


Vamos a seguir aprendiendo Elixir porque me gustan estos, post continuados. 

Elixir tiene varios tipos de colecciones: List, tuples, keywords, maps. Empecemos con listas o list en ingles.

Las listas son colecciones simples de datos que pueden ser de diferente tipo. Y puede contener valores repetidos:

iex> [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]

Elixir implementa las listas como listas linkeadas. Por esa razón llegar al elemento n tiene complejidad o(n) . Pero es muy eficiente cuando se agregan datos:

iex> list = [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
iex> ["π"] ++ list
["π", 3.14, :pie, "Apple"]
iex> list ++ ["Cherry"]
[3.14, :pie, "Apple", "Cherry"]

Si queremos concatenar 2 listas debemos usar el operador ++

iex> [1, 2] ++ [3, 4, 1]
[1, 2, 3, 4, 1]

Podemos quitar elementos o sustraerlos con el operador -- 

iex> [1,2,2,3,2,3] -- [1,2,3,2]
[2, 3]

Con la función hd (head) podemos conocer el comienzo de la lista y con tl (tail) podemos conocer el resto de la lista: 

 iex> hd [3.14, :pie, "Apple"]
3.14
iex> tl [3.14, :pie, "Apple"]
[:pie, "Apple"]

A la vez podemos utilizar pattern matching  y el operador | nos permite asignar los valores: 

iex> [h|t] = [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
iex> h
3.14
iex> t
[:pie, "Apple"]

Las tuplas son similares a las listas pero esta estructura se guarda secuencial en memoria por lo que es más rápida a la hora de acceder pero muy lenta cuando queremos insertar un elemento en el medio. 

iex> {3.14, :pie, "Apple"}
{3.14, :pie, "Apple"}

Esto se utiliza mucho cuando necesitamos que una función retorne muchos datos. 

iex> File.read("path/to/existing/file")
{:ok, "... contents ..."}
iex> File.read("path/to/unknown/file")
{:error, :enoent}

Las listas clave/valor y mapas están asociados a las colecciones, es decir listas clave/valor son un tipo de tuplas y esto mejora la performance: 

iex> [foo: "bar", hello: "world"]
[foo: "bar", hello: "world"]
iex> [{:foo, "bar"}, {:hello, "world"}]
[foo: "bar", hello: "world"]

Hay tres características a tener en cuenta: 
  • Las claves son atómicas
  • No se pueden repetir 
  • Y están ordenadas
Por estas razones, las listas clave/valor se utilizan con más frecuencia para pasar opciones a funciones.

Los mapas son un tanto diferentes a las listas clave/valor. En los mapas se puede tener claves de cualquier tipo y las claves no están ordenadas. Para construir un mapa utilizamos %{}

iex> map = %{:foo => "bar", "hello" => :world}
%{:foo => "bar", "hello" => :world}
iex> map[:foo]
"bar"
iex> map["hello"]
:world

En Elixir 1.2 las variables pueden ser claves:

iex> key = "hello"
"hello"
iex> %{key => "world"}
%{"hello" => "world"}

Si se duplica una clave pisa el valor anterior:

iex> %{:foo => "bar", :foo => "hello world"}
%{foo: "hello world"}

Como podemos ver en la salida anterior, existe una sintaxis especial para mapas que contienen sólo claves atómicas:

iex> %{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}

iex> %{foo: "bar", hello: "world"} == %{:foo => "bar", :hello => "world"}
true

Otra propiedad interesante de los mapas es que proporcionan su propia sintaxis para actualizar y acceder a las claves atómicas:

iex> map = %{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}
iex> %{map | foo: "baz"}
%{foo: "baz", hello: "world"}
iex> map.hello
"world"

Dejo link: https://elixirschool.com/lessons/basics/collections/