Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Elixir

WebApplication.livemd

Elixir

Beispiele

[a, a] = [1, 1]
a = 1
1 = a

1. Vorlesung

Funktion, um Länge einer Liste zu berechnen

defmodule Li do
  def len(list) do
    if list == [] do
      0
    else
      [h | t] = list
      1 + len(t)
    end
  end
end

list = [1, 2, 3, 4, 5, 2]

Li.len(list)

[h | t]

h = erste Element in der Liste

t = Rest der Liste


Funktion zur Berechnung der Länge einer Liste mit Tail-Recursion

defmodule Li2 do
  def len(list) do
    tail_len(list, 0)
  end

  defp tail_len(current, acc) do
    if current == [] do
      acc
    else
      [h | t] = current
      tail_len(t, acc + 1)
    end
  end
end

Li2.len(list)

Funktion, um durch Liste zu gehen und bei gewissen Wert zu stoppen.

defmodule Li3 do
  def tw(list, p) do
    tail_tw(list, p, [])
  end

  defp tail_tw([], _p, acc) do
    acc
  end

  defp tail_tw([h | t], p, acc) do
    if p.(h) do
      tail_tw(t, p, acc ++ [h])
    else
      acc
    end
  end
end

list2 = [1, 2, 3, 4, 5, 2]

Li3.tw(list2, fn x -> x <= 3 end)

Funktionen um n Elemente eine Liste zu nehmen oder aus der Liste rauszuschmeißen

defmodule Li4 do
  def take(list, i) do
    tail_take(list, i, [])
  end

  defp tail_take(_, 0, acc) do
    acc
  end

  defp tail_take([h | t], n, acc) do
    tail_take(t, n - 1, acc ++ [h])
  end

  def drop(list, i) do
    tail_drop(list, i)
  end

  defp tail_drop(list, 0) do
    list
  end

  defp tail_drop([h | t], n) do
    tail_drop(t, n - 1)
  end
end

Li4.take(list, 2)
Li4.drop(list, 3)

Funktion, die Elemente aus Liste entfernt, bis Bedingung erfüllt ist.

defmodule Li5 do
  def drop_while(list, p) do
    tail_drop_while(list, p)
  end

  defp tail_drop_while([], p) do
    []
  end

  defp tail_drop_while([h | t], p) do
    if p.(h) do
      tail_drop_while(t, p)
    else
      [h | t]
    end
  end
end

list = [2, 4, 1, 5, 10, 6, 4]

Li5.drop_while(list, fn x -> x <= 4 end)

Funktion, um List zu reversen

defmodule Li6 do
  def reverse_list(list) do
    tail_reverse_list(list, [])
  end

  defp tail_reverse_list([], acc) do
    acc
  end

  defp tail_reverse_list([h | t], acc) do
    tail_reverse_list(t, [h | acc])
  end
end

Li6.reverse_list(list)

Beispiel für Pipes

list |> Li4.take(3) |> Li6.reverse_list()

2. Vorlesung

Pipe Semantic bedeutet das gleiche wie:

list = [1, 2, 3, 4]
l2 = ["a", "b", "c"]

list |> Enum.zip(l2)

# das gleiche wie

Enum.zip(list, l2)

Aufgabe Folie 14

# Alle geraden Elemente in Liste werden neue Liste
defmodule Task14 do
  def all_even(list) do
    tail_all_even(list, [])
  end

  defp tail_all_even([], acc) do
    acc
  end

  defp tail_all_even([h | t], acc) do
    if rem(h, 2) == 0 do
      tail_all_even(t, acc ++ [h])
    else
      tail_all_even(t, acc)
    end
  end
end

list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Task14.all_even(list)
# Alle Elemente die kleiner sind als 42, werden eine neue Liste
defmodule Task15 do
  def all_large(list) do
    tail_all_large(list, [])
  end

  defp tail_all_large([], acc) do
    acc
  end

  defp tail_all_large([h | t], acc) do
    if h < 42 do
      tail_all_large(t, acc ++ [h])
    else
      tail_all_large(t, acc)
    end
  end
end

list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 55, 66, 77, 88]

x = Task15.all_large(list)

IO.inspect(x, charlists: :as_lists)

Filter

defmodule Task16 do
  def all_large(list) do
    filter(list, fn x -> x > 42 end)
  end

  def filter(list, predicate) do
    tail_filter(list, predicate, [])
  end

  defp tail_filter([], _, acc) do
    acc
  end

  defp tail_filter([h | t], predicate, acc) do
    if predicate.(h) do
      tail_filter(t, predicate, acc ++ [h])
    else
      tail_filter(t, predicate, acc)
    end
  end
end

list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 55, 66, 77, 88]

x = Task16.all_large(list)

IO.inspect(x, charlists: :as_lists)

Mehrere Pipes aneinander reihen

x =
  1..10
  |> Enum.to_list()
  |> Enum.filter(fn n -> n < 5 end)

Map und Filter

defmodule Filter do
  def all_large(list) do
    filter(list, fn x -> x > 42 end)
  end

  def filter(list, predicate) do
    tail_filter(list, predicate, [])
  end

  defp tail_filter([], _, acc) do
    acc
  end

  defp tail_filter([h | t], predicate, acc) do
    if predicate.(h) do
      tail_filter(t, predicate, acc ++ [h])
    else
      tail_filter(t, predicate, acc)
    end
  end
end

# Modul Name Map kann nicht genutzt werden
defmodule Map1 do
  def map(list, f) do
    tail_map(list, f, [])
  end

  defp tail_map([], _, acc) do
    acc
  end

  defp tail_map([h | t], f, acc) do
    tail_map(t, f, acc ++ [f.(h)])
  end
end

list = [1, 2, 3, 4, 5, 6]

# [1, 3, 5]
list
|> Filter.filter(fn n -> rem(n, 2) == 1 end)
# [2, 6, 10]
|> Map1.map(fn n -> 2 * n end)

Comprehensions

# <- zeigt an, dass n den Wert aus der Range (Bereich) 1..10 erhält.
for n <- 1..10, rem(n, 2) == 0 do
  n * n
end

# ist dasselbe wie
squared_even_numbers =
  1..10
  |> Enum.filter(fn n -> rem(n, 2) == 0 end)
  |> Enum.map(fn n -> n * n end)
# ohne das letzte , von den Folien
for n <- 1..10, rem(n, 2) == 0, into: MapSet.new() do
  n * n
end
# andere Syntax geht auch
1..10 |> Enum.filter(fn n -> rem(n, 2) == 0 end) |> Enum.map(fn n -> n * n end)
for n <- 1..10, into: MapSet.new() do
  rem(n, 2)
end
for x <- 1..20,
    y <- 9..11,
    z <- 155..161,
    x * y == z do
  IO.inspect({x, y, z})
end
for a <- 1..333,
    b <- (a + 1)..666,
    c = 1000 - a - b,
    a * a + b * b == c * c do
  IO.inspect({a, b, c})
end

Reduce

defmodule Reduce do
  def sum(list) do
    # tail_sum(list, 0)
    reduce(list, 0, fn h, acc -> acc + h end)
  end

  # defp tail_sum([], acc) do acc end
  # defp tail_sum([h|t], acc) do
  #  tail_sum(t, acc+h)
  # end

  def to_set(list) do
    # tail_to_set(list, MapSet.new())
    reduce(list, MapSet.new(), fn h, acc -> MapSet.put(acc, h) end)
  end

  # defp tail_to_set([], acc) do acc end
  # defp tail_to_set([h|t], acc) do
  #  tail_to_set(t, MapSet.put(acc, h))
  # end

  def reduce(list, default, f) do
    tail_reduce(list, default, f)
  end

  defp tail_reduce([], acc, _) do
    acc
  end

  defp tail_reduce([h | t], acc, f) do
    tail_reduce(t, f.(h, acc), f)
  end

  def map_by_reduce(list, f) do
    reduce(list, [], fn h, acc -> acc ++ [f.(h)] end)
  end
end

list = [1, 2, 3, 4, 5, 6, 1, 2, 3]

# list |> Reduce.sum()
# list |> Reduce.to_set()
list |> Reduce.map_by_reduce(fn x -> x + 1 end)
# list |> Reduce.map_by_reduce(fn x -> rem(x, 3) end)

Eager and Lazy Evaluation

a = 1..10 |> Enum.to_list()
a |> Enum.map(fn n -> IO.inspect(n) end) |> Enum.take(2)
a = 1..10 |> Enum.to_list()
a |> Stream.map(fn x -> IO.inspect(x) end)
a = 1..10 |> Enum.to_list()
a |> Stream.map(fn x -> IO.inspect(x) end) |> Enum.take(2)
Stream.iterate(0, fn n -> n + 1 end) |> Enum.take(10)
l1 = ["a", "b", "c"]
nat = Stream.iterate(1, fn n -> n + 1 end)

l1 |> Enum.zip(nat)