Wstęp do języka Elixir (Składnia)
Nil
nil
To_jest_atom
:to_tez
is_atom(To_jest_atom)
String
-
String - nowy typ, nadbudowany nad binary
-
Lista znaków też jest: ‘alamakota’
#'Lista znaków'
#'ab'++'cde'
#"Ciąg znaków"
"Ala" <> " ma kota"
Zmienne
-
Zmienne są mutowalne
-
Nazywamy je małą literą
z = 2
z
Kolekcje
Krotki
a = Siema
tuple = {a,2,:bajo_jajo}
elem(tuple, 1)
tp = {:ok, 42}
{:ok, val} = tp
val
Listy
-
Również bez większych zmian
list = [1,2,:ala_ma_kota]
list = list ++ [3,4.0]
[head | tail] = list
tail
Proplists
-
Sugar syntax, klucze to atomy
lista = [ala: "makota", akto: "maalę"]
Keyword.get(lista,:ala)
Mapy
-
Po prostu inne składniowo, ale zamysłowo to samo
mapa = %{:key => "value", 4 => 5}
element = mapa[:key]
new_mapa = %{mapa | :key => "val3"} #Tylko nadpisanie
new_mapa.key #tylko jak klucz to atom
Map.put(new_mapa, :key3, 15) #Trzeba to przypisać
Map.delete(new_mapa, :key)
Pattern Matching
-
Teraz = to nie operator Pattern Matchingu tylko przypisania
-
W Elixir mamy ^wyrażenie (Czyli bez przypisania)
^x = 3
List Comprehensions
list = for x <- [1,2,3,4] do x+1 end
list2 = for x <- 1..10, rem(x,2) == 0 do x end
#Do proplist też działa
proplist = for {_k, v} <- %{:k1=>1,:two=>"two",3=>:three}, do: v #dwie składnie
Warunki
if
ala = :makota
if ala == :makota do
"Ala ma psa"
else
ala = :juzniemakota
"Ala miała kota"
end
cond
ala = :makota
cond do
ala == :makota -> "Ma kota"
ala == :mapsa -> "Ma psa"
true -> "Nie ma nic XD"
end
case
a = 1
case a do
{12} -> 12
:aa -> :aa
z when is_atom(z) -> z
_ -> :cos
end
Moduły i funkcje
-
W pliku może być kilka modułów
defmodule Hi do
def hello(name) do
"Hello, "<>name
end
end
Hi.hello("Mati")
-
Funkcje defaultowo są exportowane
-
defp tworzy funkcje prywatną
defmodule MyModule do
def a() do
:sayA
end
defp b() do
:sayBB
end
end
MyModule.b()
defmodule Rec do
def factorial(0) do 1 end
def factorial(n) do factorial(n-1)*n end
def makota() do :makota end
end
Rec.factorial(5)
defmodule Recursion do
def niemakota do :niemakota end
def ilekotow k do "kotow #{k} jest" end
def ilekotowapsow k, l do "kotow #{k} jest, psow: #{l}" end
end
Recursion.ilekotow(3)
defmodule A do
def f(x \\ 3) do
"Liczba: #{x}"
end
end
A.f()
Funkcje anonimowe
sum = fn (a,b) -> a+b end
sum.(3,4)
up = &String.upcase/1
up.("alamakota")
-
Dla notacji & oznaczenie &1 to oznacza argument 1
Pipe
"ala ma kota" |> String.upcase |> String.split
"ala ma kota" |> String.to_charlist() |> Enum.map(& (&1+1)) |> to_string
#Atrybuty modułów
defmodule Makota do
@makota "ma kota!"
def ma kto do
"#{kto} #{@makota}"
end
end
Makota.ma("Cuś")
Struktury
-
To tak na prawdę mapa (sugar syntax)
-
Tylko jedna struktura na moduł
defmodule Person do
defstruct name: "", surname: "", sex: :unknown
end
default = %Person{}
Procesy
defmodule ProcModule do
def printAndSpawn(0) do nil end
def printAndSpawn(n) do
spawn(__MODULE__, :printAndSpawn, [n-1])
Process.sleep(:rand.uniform(1000)) #rand wywołany z Erlanga
IO.puts("terminating #{n}")
end
end
ProcModule.printAndSpawn(5)
Komunikacja międzyprocesowa
-
Nie ma !
-
funk!(a) to legalna nazwa funkcji
defmodule Receiver do
def printMessage do
receive do
message -> IO.puts("got: #{message}")
end
printMessage()
end
end
pid = spawn(Receiver, :printMessage, [])
send(pid, "Ala ma kota")
Protokoły
-
Protokoły = Interface
-
Czyli implementace dla różnych typów
defprotocol Empty do
def empty? (t)
end
defimpl Empty, for: List do
def empty? (l) do
length(l) == 0
end
end
defimpl Empty, for: Map do
def empty?(m), do: map_size(m) == 0
end
Empty.empty?([])
-
Wbudowanymi protokołami jest np Enum lub Stream (leniwy Enum)