erang wokshop ii
TRANSCRIPT
Erlang/OTP WorkshopProgramowanie funkcyjne w Erlangu 19.01.2011r.
Arek Flinik [email protected]
Wrocławska grupa użytkowników Erlanga
KNSIPPT
środa, 19 stycznia 2011
Ściągawka
W pliku: -module(przyklad). -compile(export_all).
W shellu: Eshell V5.7.21>c(przyklad).{ok,test}2>
środa, 19 stycznia 2011
Programowanie funkcyjneAlonzo Church1930rachunek lambda
alewolimy myśleć jak o funkcjach matematycznych
środa, 19 stycznia 2011
Programowanie funkcyjne
silnia(N) -> if
N=:=0 -> 1; N > 0 -> N*silnia(N-1)
end
silnia(x) = { 1 jeśli n=0n*silnia(n-1) jeśli n>0
środa, 19 stycznia 2011
Funkcje w Erlangu
function(X) ->Expression.
Pattern Matchingfunction(X) ->Expression;function(Y) ->Expression;function(_) ->Expression.
środa, 19 stycznia 2011
Guard (czyli strażnik)
sprzedaj_piwo(Wiek) when Wiek >= 18 -> true;sprzedaj_piwo(_) -> false.
środa, 19 stycznia 2011
If-Then-Elseczyli da się inaczej
sprzedaj_piwo(Wiek) -> if Wiek >= 18 -> tak; Wiek >= 15 -> moze; true -> nie end.
środa, 19 stycznia 2011
If-Then-Elseczyli da się inaczej
sprzedaj_piwo2(Wiek) -> if Wiek >= 15 -> moze; Wiek >= 18 -> tak; true -> nie end. 1>sprzedaj_piwo2(20).moze
co się stanie?
środa, 19 stycznia 2011
If-Then-Elseczyli da się inaczejsprzedaj_piwo(Wiek) -> if Wiek >= 18 -> tak; Wiek >= 15 -> moze; true -> nie end.
sprzedaj_piwo3(Wiek) -> if Wiek >= 18 -> tak; Wiek >= 15 -> moze; Wiek < 15 -> nie end.
Lepiej:
środa, 19 stycznia 2011
Guard expressionsMożemy używać tylko:
porównań zmiennych, operatorów logicznych, wyrażeń arytmetycznych
Oraz BIFów:is_atom/1, is_binary/1, is_bitstring/1, is_float/1, is_function/1, is_function/2, is_integer/1, is_list/1, is_number/1, is_pid/1, is_port/1, is_record/2,
is_record/3, is_reference/1, is_tuple/1,abs(Number), bit_size(Bitstring), byte_size
(Bitstring), element(N, Tuple), float(Term), hd(List), length(List), node(), node(Pid|Ref|Port), round(Number), self(), size(Tuple|Bitstring), tl
(List), trunc(Number), tuple_size(Tuple),
środa, 19 stycznia 2011
Case
na_plazy(Temperatura) ->case Temperatura of {celsius, N} when N >= 18, N =< 45 -> 'jest ok'; {kelvin, N} when N >= 293, N =< 318 -> 'jest ok'; {fahrenheit, N} when N >= 68, N =< 113 -> 'jest ok... w USA'; _ -> 'lepiej tam nie isc'end.
środa, 19 stycznia 2011
Casea co gdy chcemy sprawdzić warunek za pomocą funkcji, która nie należy do dozwolonych?wiek_ok(Wiek) when Wiek > 17 -> true;wiek_ok(_) -> false. sprzedaj_piwo(Wiek) when wiek_ok(Wiek) -> ... * 1: illegal guard expression
sprzedaj_piwo(Wiek) -> Ok = wiek_ok(Wiek), case Ok of false -> nie; true -> tak end.
środa, 19 stycznia 2011
Przypomnienie: listy
Lista = [1,2,3,5][H|T] = ListaH = 1T = [2,3,5]
środa, 19 stycznia 2011
Przypomnienie: listy
Lista = [1,2,3,5][H|T] = ListaH = 1T = [2,3,5]
Lista2 = [a][H2|T2] = Lista2H2 = aT2 =[]
środa, 19 stycznia 2011
Przypomnienie: listy
Konkatenacja: operator ++
1>[1,2,3] ++ [4,5]. [1,2,3,4,5]
Uwaga: działa wolno, więc unikamy gdzie tylko to możliwe!
środa, 19 stycznia 2011
Rekurencja
factorial(0) -> 1;factorial(N) -> N * factorial(N-1).
środa, 19 stycznia 2011
Rekurencja - efektywność?tail recursion
int fact(int n){ if(n>1){ return n*fact(n-1); } else{ return 1; }}
int fact2(int n, int acc){ if(n>1){ return fact2(n-1, acc*n); } else{ return acc; }}
środa, 19 stycznia 2011
Rekurencja - efektywność?tail recursion
Podobnie w erlangu:
factorial(0) -> 1;factorial(N) -> N * factorial(N-1).
factorial(1, Acc) -> Acc;factorial(N, Acc) -> factorial(N-1, N*Acc).
factorial(N) -> factorial(N,1).
środa, 19 stycznia 2011
Jak operujemy na listach?
int suma = 0;for (i=0;i<10; i++) { suma += tab[i];}
środa, 19 stycznia 2011
Jak operujemy na listach? int suma = 0;for (i=0;i<10; i++) { suma += tab[i];}
sum([]) -> 0; sum([H|T]) -> H + sum(T).
środa, 19 stycznia 2011
Ćwiczenie: reverseDane: lista T np: [3,1,4,1,5]
Wynik: odwrócona lista T np: [5,1,4,1,3]
Eshell V5.7.21>reverse([a,b,c,d,e]).[e,d,c,b,a].2>
środa, 19 stycznia 2011
Ćwiczenie: reverse
reverse([]) -> [];reverse([H|T]) -> reverse(T) ++ [H].
środa, 19 stycznia 2011
Ćwiczenie: reverse
reverse([]) -> [];reverse([H|T]) -> reverse(T) ++ [H].
Da się lepiej!
środa, 19 stycznia 2011
Ćwiczenie: reverse
reverse([]) -> [];reverse([H|T]) -> reverse(T) ++ [H].
reverse([], Acc) -> Acc;reverse([H|T], Acc) -> reverse(T, [H|Acc]).
reverse(List) -> reverse(List, []).
środa, 19 stycznia 2011
List Comprehensions
{3×n : n ∈ {1,2,3,4} } = {3,6,9, 12}
1> [3*N || N <- [1,2,3,4]].[3,6,9,12]2> [2*X-Y || X <- [1,2,3,4], Y <- [1,0]]. [1,2,3,4,5,6,7,8]
środa, 19 stycznia 2011
List Comprehensionstrochę trudniejszy przykład
qsort([Pivot|T]) ->qsort([ X || X <- T, X < Pivot]) ++[Pivot] ++qsort([ X || X <- T, X >= Pivot]);qsort([]) -> [].
środa, 19 stycznia 2011
List Comprehensionstrochę trudniejszy przykład
qsort([Pivot|T]) ->sort([ X || X <- T, X < Pivot]) ++[Pivot] ++sort([ X || X <- T, X >= Pivot]);qsort([]) -> [].
Znaczniekrócej
niż w
C/C#/
Javie...
środa, 19 stycznia 2011
Zadanie!
Napiszmy prostą bazę danych operującą na liście krotek. Przykładowa baza:[{zygfryd, 505123456}, {zuza, 661009988}, {alarm, 911}]
środa, 19 stycznia 2011
Zadanie!Napiszmy prostą bazę danych operującą na liście krotek. Przykładowa baza:[{zygfryd, 505123456}, {zuza, 661009988}, {alarm, 911}]
Zaimplementuj funkcje:create/1 create(Pair) -> {ok,NewDb}insert/2 insert(Db, Pair) -> NewDb find/2 find(Db, Key) -> {Key, Value}delete/2 delete(Db, Key) -> {NewDb, {Key, Value}}update/3 update(Db, Key, Value) -> NewDB
gdzie: Db, NewDb - to baza taka jak zdefiniowana powyżej, pair - {Key, Value}
środa, 19 stycznia 2011
Zadanie domowe!Zmodyfikujmy bazę, aby mogła przechowywać kilka par z takim samym kluczem.
Zaimplementuj funkcje używając list comprehensions:
find_all/2 (zwraca listę krotek o danym kluczu)find_all(Db, Key) -> [{Key, Value}, {Key, Value2}...]
delete_all/2 (usuwa wszystkie krotki o danym kluczu)delete_all(Db, Key) -> {NewDb, [{Key, Value}, {Key, Value2}, ...]}
środa, 19 stycznia 2011
Zadanie domowe!Zmodyfikujmy bazę, aby mogła przechowywać kilka par z takim samym kluczem.
Dla ambitnych!
update_all/3 update_all(Db, Key, Function) -> NewDB
Trzecim argumentem jest funkcja, która powinna być zaaplikowana do
wszystkich krotek z pasującym kluczem. update_all([{a,4}, {b,3}, {a,6}], a, fun(X) -> 2*X end).[{a,8}, {b,3}, {a,12}]
środa, 19 stycznia 2011