Warning: strpos() [function.strpos]: Empty needle in /home/dealer/kasat/pkg/cahir/web/html/lib/plugins/translation2/action.php on line 53

Warning: Cannot modify header information - headers already sent by (output started at /home/dealer/kasat/pkg/cahir/web/html/lib/plugins/translation2/action.php:53) in /home/dealer/kasat/pkg/cahir/web/html/inc/actions.php on line 163
erlang:funs [Krystian Bacławski Wiki]
 

Funkcje - Funkcje

Składnia

Deklaracja funkcji

Składnia:

Name(Pattern11,...,Pattern1N) [when Guard1] ->
  Body1;
...;
Name(PatternK1,...,PatternKN) [when GuardK] ->
  BodyK.

Opis:

  • Każda funkcja posiada sygnaturę w postaci m:f/n. Gdzie:
  • m jest modułem, w którym funkcja została zadeklarowana,
  • f jest nazwą funkcji,
  • n jest arnością funkcji.
  • Sygnatura wyznacza unikalność funkcji w systemie.
  • Funkcje można przeciążać ze względu na ilość argumentów.
  • Deklaracja funkcji składa się z klauzul.
  • Każda klauzula kończy się średnikiem, a ostatnia kropką.
  • Każda klauzula może posiadać opcjonalnego strażnika.

Ewaluacja i aplikacja

Ewaluacja funkcji:

  • Klauzule są przeglądane od pierwszej do ostatniej.
  • Jeśli wzorce się dopasują i strażnik zwróci true, ciało klauzuli się wykona.
  • Wartość funkcji jest wartością obliczoną przez ciało klauzuli.
  • Funkcja zawsze ma wynik. Zwyczajowo zwraca się atom ok.

Aplikacja argumentów:

  • Nie ma wbudowanych środków do częściowej aplikacji.
  • Nie ma ustalonego porządku aplikowania argumentów.
  • Pełną aplikacji można dokonać również przy pomocy funkcji apply/3.

Przykład:

1> c(demo).
{ok,demo}
2> demo:double(4).
8
2> apply( demo, double, [3] ).
6

Strażnicy

Podstawy

Strażnik to podzbiór wyrażeń Erlangowych używany do nakładania więzów na funkcje lub ogólniej dopasowanie wzorca.

Prawidłowo skonstruowany strażnik może składać się z:

  • związanych zmiennych,
  • uproszczonych wyrażen Erlangowych,
  • testów sprawdzających typy,
  • porównania wyrażeń,
  • obliczeń arytmetycznych,
  • wyrażeń boolowskich,
  • wbudowanych funkcjach mogących służyć jako strażnik.

Przykład:

guard(X,Y) when not (((X > Y) or not(is_atom(X))
  and is_atom(Y) or (X == 3.4))) -> X + Y.

Składanie strażników

Alternatywa strażników:

Guard1; ...; GuardN
  • Powyższa składnia czasami jest utożsamiana z sekwencją strażników.
  • Strażnicy oddzieloni średnikiem.
  • Wyrażenie prawdziwe, jeśli co najmniej jedna ze składowych jest prawdziwa.
  • Jeśli jeden ze strażników zwrócił prawdę pozostałe nie są ewaluowane.

Koniunkcja strażników:

Guard1, ..., GuardN
  • Powyższa składnia czasami jest utożsamiana ze strażnikiem.
  • Strażnicy oddzieloni przecinkiem.
  • Wyrażenie jest prawdziwe, jeśli wszystkie składowe są prawdziwe.

Przykład:

guard(X,Y) when not(X > Y), is_atom(X); not(is_atom(Y)), X =/= 3.4 -> X + Y.

BIFs będące strażnikami

Funkcje sprawdzające typ:

is_atom/1 is_function/2 is_port/1
is_binary/1 is_integer/1 is_record/2
is_bitstring/1 is_list/1 is_record/3
is_float/1 is_number/1 is_reference/1
is_function/1 is_pid/1 is_tuple/1

Inne funkcje wbudowane mogące służyć jako strażnicy:

abs/1 element/2 length/1 round/1 tl/1
bit_size/1 float/1 node/0 self/0 trunc/1
byte_size/1 hd/1 node/1 size/1 tuple_size/1

Funkcje anonimowe

Składnia

Składnia:

fun
  (Pattern11,...,Pattern1N) [when GuardSeq1] ->
    Body1;
  ...;
  (PatternK1,...,PatternKN) [when GuardSeqK] ->
    BodyK
end

Przykład:

1> Fun1 = fun (X) -> X+1 end.
#Fun<erl_eval.6.39074546>
2> Fun1(2).
3
3> Fun2 = fun (X) when X>=5 -> gt; (X) -> lt end.
#Fun<erl_eval.6.39074546>
4> Fun2(7).
gt

Funkcje anonimowe jako predykaty

double( L ) ->
  lists:map( fun( X ) -> 2 * X end, L ).
increment( L ) ->
  lists:map( fun( X ) -> 1 + X end, L ).
 
print_list( S, L ) ->
  lists:foreach( fun( H ) -> io:format( S, "~p~n", [ H ] ) end, L ).
broadcast( M, L ) ->
  lists:foreach( fun( Pid ) -> Pid ! M end, L ).

Funkcje wyższego rzędu

Co to jest funkcja wyższego rzędu?

Funcja wyższego rzędu albo funkcjonał to funkcja, która spełnia co najmniej jeden z poniższych warunków:

  • Przyjmuje co najmniej jedną funkcję jako argument.
  • Zwraca funkcję.

Najczęściej spotykane funkcjonały w języka funkcyjnych (Czyli kilka funkcjonałów z modułu lists):

  • all/2 - jeśli predykat spełniony dla wszystkich to zwróć true.
  • dropwhile/2 - porzucaj elementy dopóki predykat spełniony, zwróć resztę.
  • filter/2 - porzucaj elementy, jeśli predykat niespełniony.
  • foldl/3 - aplikuj funkcję o arności 2 od lewej, zacznij od podanego akumulatora.
  • foreach/2 - aplikuj predykat do każdego elementu.
  • map/2 - aplikuj predykat do każdego elementu i zwróć listę wyników.
  • partition/2 - zwróć parę list, dla pierwszej predykat spełniony, dla drugiej nie.

Przykłady funkcjonałów biorących za argument predykat

any(Pred, [H|T]) ->
  case Pred(H) of
    true  ->  true;
    false ->  any(Pred, T)
  end;
any(Pred, []) -> false.
 
filter(F, [H|T]) ->
  case F(H) of
    true  -> [H|filter(F, T)];
    false -> filter(F, T)
  end;
filter(F, []) -> [].
 
map(F, [H|T]) ->
  [F(H)|map(F, T)];
map(F, []) ->
  [].
 
foreach(F, [H|T]) ->
  F(H),
  foreach(F, T);
foreach(F, []) ->
  ok.

Funkcje jako argumenty funkcji

Funkcje można przekazywać do funkcjonałów jako:

  • funkcję anonimową,
  • zmienną, do której została przypisana funkcja,
  • uchwyt do funkcji lokalnej lub globalnej.

Przykład:

map_square( L ) -> F = fun( X ) -> X * X end, lists:map( F, L ).
 
map_to_string( L ) -> lists:map( fun erlang:integer_to_list/1, L ).
 
test() ->
  Seq = lists:seq( 1, 10 ),
  lists:foreach(
    fun( F ) -> io:format( "~p~n", [ apply( F, [ Seq ] ) ] ) end,
    [ fun map_square/1, fun map_to_string/1 ]).
 
2> test:test().
[1,4,9,16,25,36,49,64,81,100]
["1","2","3","4","5","6","7","8","9","10"]
ok

Funkcje jako wynik funkcji

Klasyfikacja wyniku funkcjonału…

Jeśli funkcjonał zwraca funkcję, to może ona być dwóch rodzajów.

  • Czysta funkcja (ang. pure function) – wynik zależy wyłącznie od jej argumentów.
  • Domknięcie (ang. closure)– wynik zależy od kontekstu, w którym została zdefiniowana. Domknięcia z racji swej natury są o wiele ciekawsze.

Przykłady:

% zwracamy czysta funkcje
palinChecker() ->
  fun( X ) ->
    X == reverse( X )
  end.
 
% zwracamy domkniecie
sendTo( Pid ) ->
  fun( Msg ) ->
    Pid ! Msg
  end.

Leniwa ewaluacja list

Leniwe obliczenia i Erlang:

Wiemy, że język jest gorliwy. Można leniwie obliczać w jawny sposób korzystając z generatorów, które można tworzyć przy pomocy domknięć. Generator to funkcja, która zwraca element i funkcję, która potrafi policzyć resztę elementów.

Można w ten sposób symulować nieskończone struktury, albo optymalizować pewną klasę obliczeń.

Przykład:

seq( Num ) ->
  fun() ->
    [ Num | seq( Num + 1 ) ]
  end.
 
2> SeqFun0 = lazy:seq(0).
#Fun<lazy.0.82459551>
3> [Seq1|SeqFun1] = SeqFun0().
[0|#Fun<lazy.0.82459551>]
4> [Seq2|SeqFun2] = SeqFun1().
[1|#Fun<lazy.0.82459551>]
 
erlang/funs.txt · Last modified: 2010/05/07 22:44 by Krystian Bacławski
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-No Derivative Works 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki