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)