Skip to content

Instantly share code, notes, and snippets.

@marpo60
Created November 10, 2022 23:10
Show Gist options
  • Save marpo60/607ba8be7cefed74be1b51b5d4f4f546 to your computer and use it in GitHub Desktop.
Save marpo60/607ba8be7cefed74be1b51b5d4f4f546 to your computer and use it in GitHub Desktop.

Conociendo Elixir - Parte 1

Mix.install([
  {:kino, "~> 0.7.0"}
])

Tipos básicos

integer = 123
float = 5.0
atom = :atom
ranges = 1..10
tuple = {:ok, 1}
list = [1, 2, 3]
maps_1 = %{a: :b}
maps_2 = %{{1, 2} => [4, 5]}
keyword_list = [a: :b]
boolean = true

Pattern Matching

a = 2
2 = a
# 3 = a

{a, b} = {1, 3}
{1, 3} = {a, b}

Funciones Anonimas

# Funcion Anonima
fn -> :a end

fn ->
  1 + 2
end

# Bind
suma = fn a, b -> IO.inspect(a + b) end
hola = fn -> IO.inspect("Hola") end
chau = fn -> IO.inspect("Chau") end

# Ejecutar
suma.(2, 3)
hola.()
chau.()
# https://hexdocs.pm/elixir/1.14.1/Date.html
Date.from_iso8601("2015-01-23") |> IO.inspect()
Date.from_iso8601("2015-991-23") |> IO.inspect()

add_10_days = fn
  {:ok, date} -> Date.add(date, 10)
  {:error, error} -> error
end

add_10_days.(Date.from_iso8601("2015-01-23")) |> IO.inspect()
add_10_days.(Date.from_iso8601("2015-99-23")) |> IO.inspect()
add_5 = fn x -> x + 5 end
add_3 = &(&1 + 3)

add_3.(1) |> IO.inspect()
add_5.(1) |> IO.inspect()

Modulos

defmodule Workshop do
  def hola() do
    IO.inspect("Hola")
  end
end

Workshop.hola()

Maps, Structs

defmodule User do
  defstruct name: ""

  def name(%User{name: name}), do: name
  def name(_), do: "Not a user"
end
user = %User{name: "Ben"}
map = %{}

User.name(user) |> IO.inspect()
User.name(map) |> IO.inspect()

List, Keyword List

list = [1, 2, 3]

# Enum es tu amigo
# https://hexdocs.pm/elixir/1.14.1/Enum.html
Enum.map(list, fn x -> x * 2 end) |> IO.inspect()

# Stream tambien es tu amigo
# https://hexdocs.pm/elixir/1.14.1/Stream.html
Stream.map(list, fn x -> x * 2 end) |> Enum.to_list() |> IO.inspect()

sleep_and_print = fn i ->
  Process.sleep(100)
  IO.inspect(i)
end

Enum.map(1..50, &sleep_and_print.(&1)) |> Enum.take(5)
Stream.map(1..50, &sleep_and_print.(&1)) |> Enum.take(5)

Control Flow

defmodule Control do
  def is_0(a) do
    if a == 0 do
      "YES"
    else
      "NO"
    end
  end

  def is_1(a) do
    case a do
      1 -> "YES"
      _ -> "NO"
    end
  end

  def is_2(a) do
    cond do
      a == 2 -> "YES"
      true -> "NO"
    end
  end

  def is_3(3), do: "YES"
  def is_3(_), do: "NO"
end

Control.is_0(0) |> IO.inspect()
Control.is_0(1) |> IO.inspect()
IO.inspect("--------------------")
Control.is_1(1) |> IO.inspect()
Control.is_1(2) |> IO.inspect()
IO.inspect("--------------------")
Control.is_2(2) |> IO.inspect()
Control.is_2(3) |> IO.inspect()
IO.inspect("--------------------")
Control.is_3(3) |> IO.inspect()
Control.is_3(4) |> IO.inspect()

Process

defmodule Stack do
  use GenServer

  # Client

  def start_link(default) when is_list(default) do
    GenServer.start_link(__MODULE__, default)
  end

  def push(pid, element) do
    Process.sleep(element)
    IO.inspect(DateTime.utc_now(), label: "#{inspect(self())} Push")
    ret = GenServer.cast(pid, {:push, element})
    IO.inspect(DateTime.utc_now(), label: "#{inspect(self())} After Push")
    ret
  end

  def pop(pid) do
    IO.inspect(DateTime.utc_now(), label: "#{inspect(self())} Pop")
    ret = GenServer.call(pid, :pop)
    IO.inspect(DateTime.utc_now(), label: "#{inspect(self())} After Pop")
    ret
  end

  # Server (callbacks)

  @impl true
  def init(stack) do
    {:ok, stack}
  end

  @impl true
  def handle_call(:pop, _from, [head | tail]) do
    Process.sleep(head)
    IO.inspect(DateTime.utc_now(), label: "#{inspect(self())} Handle call")
    {:reply, head, tail}
  end

  @impl true
  def handle_cast({:push, element}, state) do
    Process.sleep(element)
    IO.inspect(DateTime.utc_now(), label: "#{inspect(self())} Handle cast")
    {:noreply, [element | state]}
  end
end

{:ok, pid_1} = GenServer.start_link(Stack, [0]) |> IO.inspect()
{:ok, pid_2} = GenServer.start_link(Stack, [0]) |> IO.inspect()

Kino.Process.render_seq_trace([pid_1, pid_2], fn ->
  tasks = [
    Task.async(fn -> Stack.push(pid_1, 2000) end),
    Task.async(fn -> Stack.push(pid_2, 20) end)
  ]

  IO.inspect(DateTime.utc_now(), label: "#{inspect(self())} Wait")
  Task.await_many(tasks)
  IO.inspect(DateTime.utc_now(), label: "#{inspect(self())} Done")

  Stack.pop(pid_2)
  Stack.pop(pid_1)
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment