if, unless, cond, case, with
x = 7
if x > 5 do
IO.puts("groß")
else
IO.puts("klein")
end
unless x == 0, do: IO.puts("nicht null")
# cond: wie if/else-if
note =
cond do
x >= 9 -> "sehr gut"
x >= 5 -> "gut"
true -> "weiter üben"
end
IO.puts(note)
# case: Pattern Matching mit Guards
beschreibe = fn wert ->
case wert do
{:ok, n} when n > 100 -> "großer Erfolg #{n}"
{:ok, n} -> "Erfolg #{n}"
{:error, grund} -> "Fehler: #{grund}"
[] -> "leere Liste"
[h | _] -> "Liste mit Kopf #{h}"
%{name: name} -> "Map mit Name #{name}"
_ -> "unbekannt"
end
end
for v <- [{:ok, 500}, {:ok, 5}, {:error, "kaputt"}, [], [9, 8], %{name: "Mia"}, 3.5], do: IO.puts(beschreibe.(v))
# with: Kette von Matches, bricht beim ersten Fehlschlag ab
def_parse = fn s ->
with {n, ""} <- Integer.parse(s),
true <- n > 0 do
{:ok, n * 2}
else
:error -> {:error, :keine_zahl}
{_, _rest} -> {:error, :ungueltig}
false -> {:error, :nicht_positiv}
end
end
IO.inspect(Enum.map(["21", "abc", "-5", "7x"], def_parse))groß nicht null gut großer Erfolg 500 Erfolg 5 Fehler: kaputt leere Liste Liste mit Kopf 9 Map mit Name Mia unbekannt [ok: 42, error: :keine_zahl, error: :nicht_positiv, error: :ungueltig]
Schleifen gibt es nicht: Enum ersetzt sie
z = [1, 2, 3, 4, 5, 6]
IO.inspect(Enum.map(z, &(&1 * &1)))
IO.inspect(Enum.filter(z, &(&1 > 3)))
IO.inspect(Enum.reject(z, &(&1 > 3)))
IO.inspect(Enum.reduce(z, 0, fn x, acc -> acc + x end))
IO.inspect(Enum.sum(z))
IO.inspect(Enum.count(z, &(rem(&1, 2) == 0)))
IO.inspect(Enum.find(z, &(&1 > 3)))
IO.inspect(Enum.all?(z, &(&1 > 0)))
IO.inspect(Enum.any?(z, &(&1 > 5)))
IO.inspect(Enum.take(z, 2))
IO.inspect(Enum.drop(z, 4))
IO.inspect(Enum.take_while(z, &(&1 < 4)))
IO.inspect(Enum.chunk_every(z, 4))
IO.inspect(Enum.zip(z, ~w(a b c)))
IO.inspect(Enum.with_index(["a", "b"]))
IO.inspect(Enum.group_by(z, &rem(&1, 3)))
IO.inspect(Enum.split_with(z, &(&1 < 3)))
IO.inspect(Enum.frequencies(~w(a b a c a)))
IO.inspect(Enum.max(z))
IO.inspect(Enum.min_by(["ccc", "a", "bb"], &String.length/1))
IO.inspect(Enum.sort(z, :desc))
IO.inspect(Enum.sort_by(["bb", "a", "ccc"], &String.length/1))
IO.inspect(Enum.uniq([1, 2, 2, 3, 1]))
IO.inspect(Enum.flat_map([1, 2], &[&1, &1 * 10]))
IO.inspect(Enum.into([a: 1, b: 2], %{}))
IO.inspect(Enum.map(%{a: 1, b: 2}, fn {k, v} -> {k, v * 2} end))
IO.inspect(Enum.reduce(1..5, 1, &*/2))
IO.inspect(Enum.scan(z, &+/2))
IO.inspect(Enum.random([42]))
IO.inspect(Enum.reverse(z) |> Enum.join(","))
IO.inspect(Enum.at(z, -1))
IO.inspect(Enum.empty?([]))
IO.inspect(Enum.member?(z, 3))
IO.inspect(Enum.dedup([1, 1, 2, 2, 1]))
IO.inspect(Enum.unzip([{1, :a}, {2, :b}]))
IO.inspect(Enum.min_max(z))[1, 4, 9, 16, 25, 36]
[4, 5, 6]
[1, 2, 3]
21
21
3
4
true
true
[1, 2]
[5, 6]
[1, 2, 3]
[[1, 2, 3, 4], [5, 6]]
[{1, "a"}, {2, "b"}, {3, "c"}]
[{"a", 0}, {"b", 1}]
%{0 => [3, 6], 1 => [1, 4], 2 => [2, 5]}
{[1, 2], [3, 4, 5, 6]}
%{"a" => 3, "b" => 1, "c" => 1}
6
"a"
[6, 5, 4, 3, 2, 1]
["a", "bb", "ccc"]
[1, 2, 3]
[1, 10, 2, 20]
%{a: 1, b: 2}
[a: 2, b: 4]
120
[1, 3, 6, 10, 15, 21]
42
"6,5,4,3,2,1"
6
true
true
[1, 2, 1]
{[1, 2], [:a, :b]}
{1, 6}for-Comprehensions
IO.inspect(for x <- 1..5, do: x * x)
IO.inspect(for x <- 1..10, rem(x, 3) == 0, do: x)
IO.inspect(for x <- 1..3, y <- ~w(a b), do: {x, y})
IO.inspect(for {k, v} <- %{a: 1, b: 2}, into: %{}, do: {v, k})
IO.inspect(for <<c <- "abc">>, do: c + 1)
IO.inspect(for x <- [1, 2, 3], y <- [1, 2, 3], x < y, do: {x, y})
IO.inspect(for {:ok, v} <- [{:ok, 1}, {:error, 2}, {:ok, 3}], do: v)
IO.inspect(for n <- 1..3, into: "", do: Integer.to_string(n))
IO.inspect(for x <- 1..4, reduce: 0 do acc -> acc + x end)[1, 4, 9, 16, 25]
[3, 6, 9]
[{1, "a"}, {1, "b"}, {2, "a"}, {2, "b"}, {3, "a"}, {3, "b"}]
%{1 => :a, 2 => :b}
'bcd'
[{1, 2}, {1, 3}, {2, 3}]
[1, 3]
"123"
10Stream: faule Auswertung
Enum arbeitet sofort, Stream baut eine Rechenvorschrift und berechnet erst bei Bedarf. So gehen auch unendliche und sehr große Folgen:
fib = Stream.unfold({0, 1}, fn {a, b} -> {a, {b, a + b}} end)
IO.inspect(Enum.take(fib, 12))
geradequadrate =
Stream.iterate(1, &(&1 + 1))
|> Stream.filter(&(rem(&1, 2) == 0))
|> Stream.map(&(&1 * &1))
IO.inspect(Enum.take(geradequadrate, 5))
IO.inspect(Stream.cycle([:a, :b]) |> Enum.take(5))
IO.inspect(1..1_000_000 |> Stream.map(&(&1 * 2)) |> Stream.take_every(250_000) |> Enum.to_list())
IO.inspect(Stream.repeatedly(fn -> 7 end) |> Enum.take(3))
IO.inspect(Stream.zip(1..3, ~w(a b c)) |> Enum.to_list())
stream = Stream.map([1, 2, 3], fn x -> IO.puts("verarbeite #{x}"); x * 10 end)
IO.puts("noch nichts passiert")
IO.inspect(Enum.to_list(stream))[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
[4, 16, 36, 64, 100]
[:a, :b, :a, :b, :a]
[2, 500002, 1000002, 1500002]
'\a\a\a'
[{1, "a"}, {2, "b"}, {3, "c"}]
noch nichts passiert
verarbeite 1
verarbeite 2
verarbeite 3
[10, 20, 30]Merke
if,unless,cond,case,withsind Ausdrücke;caseundwithnutzen Pattern Matching- Keine Schleifen:
Enum.map/filter/reduce/...undfor-Comprehensions Streamist lazy, ideal für große oder unendliche Folgen- Die Pipe verbindet alles zu lesbaren Ketten
Aufgabe
Berechne die Summe der Quadrate aller ungeraden Zahlen bis 100 mit einer Pipe und Enum.