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:database:match_spec [Krystian Bacławski Wiki]
 

Match specifications

Wprowadzenie

Zapytanie dopasowujące:

  • jest tworem zachowującym się podobnie do funkcji,
  • ma postać postaci uproszczonego termu erlangowego,
  • jest dużo wydajniejsze od zwykłej funkcji,
  • może wywoływać funkcje będące wyłącznie BIF-ami (tak samo jak w strażnikach),
  • są nieczytelne ;-)

Można dopasowywać dowolne wyrażenia, ale stosowane głównie wraz z:

  • ETS – np. ets:match/2,
  • śledzeniem wywołań – np. erlang:trace_pattern/2.

Każde zapytanie dopasowujące posiada trzy części:

  • argumenty (głowę) – pełniące podobną rolę do argumentów funkcji, tj. argumenty podane do funkcji zostają związane z nazwami używanymi wewnątrz funkcji, w przypadku zapytań dopasowujących wszystkie zmienne mają postać $<int>,
  • warunki – więzy, które mają być zastosowane na zmiennych,
  • akcje – zestaw akcji, które mają zostać podjęte jeśli dopasowanie argumentów oraz sprawdzanie warunków się powiodło.

Części

Argumenty - MatchHead

Specyfikator argumentów zostaje dopasowany do przekazanych do funkcji parametrów.

W przypadku zapytań dopasowujących typu ets argument musi być krotką lub pojedynczą zmienną.

MatchHead ::= MatchVariable | '_' | [ MatchHeadPart, ... ]
MatchHeadPart ::= term() | MatchVariable | '_'
MatchVariable ::= '$<num>'

Przykłady

[]                  %% funkcja bezargumentowa
'_'                 %% funkcja jednoargumentowa, argument nie zostaje związany
'$1'                %% funkcja jednoargumentowa, parametr związany z '$1'
{'$1','$2'}         %% funkcja jednoargumentowa, parametr musi być krotką o długości dwa
[ foobar, _, '$1']  %% funkcja trójargumentowa, pierwszy parametr musi być atomem foobar, drugi nie zostaje związany, trzeci związany z '$1'

Warunki - MatchConditions

Błąd w konstrukcji MatchCondition powoduje natychmiastowe rzucenie wyjątkiem badarg.

MatchConditions ::= [ MatchCondition, ...] | []
MatchCondition ::=
  { GuardFunction } |
  { GuardFunction, ConditionExpression, ... }
ConditionExpression ::=
  ExprMatchVariable |
  { GuardFunction } |
  { GuardFunction, ConditionExpression, ... } | 
  TermConstruct
ExprMatchVariable ::=
  MatchVariable |  % związana w argumentach
  '$_' |           % rozwija się do całego wyrażenia MatchHead
  '$$'             % rozwija się do ['$1','$2', ...]
TermConstruct =
  {{}} | {{ ConditionExpression, ... }} |
  [] | [ConditionExpression, ...] |
  NonCompositeTerm | {const, term()}
NonCompositeTerm ::= term() %% typ złożony niedozwolony
GuardFunction ::=
  is_atom | is_constant | is_float | is_integer | is_list | is_number | is_pid | is_port |
  is_reference | is_tuple | is_binary | is_function | is_record |
  'and' | 'or' | 'not' | 'xor' | andalso | orelse | 
  abs | element | hd | length | node | round | size | tl | trunc |
  '+' | '-' | '*' | 'div' | 'rem' | 'band' | 'bor' | 'bxor' | 'bnot' | 'bsl' | 'bsr' |
  '>' | '>=' | '<' | '=<' | '=:=' | '==' | '=/=' | '/=' |
  self

Przykłady

% pierwszy parametr to atom
[{is_atom,'$1'}]
% oba parametry to liczby całkowite, pierwsza większa od drugiej
[{'and',{is_integer,'$1'},{is_integer,'$2'},{'>','$1','$2'}}]

Akcje - MatchBody

W wariancie ets akcja jest jedna i wylicza rezultat zapytania.

MatchBody ::= [ ActionTerm ]
ActionTerm ::= ConditionExpression | ActionCall
ActionCall ::= ...

Przykłady

['$2']
['$_']
[{result,$1,true,$3}]

Wykonywanie

Wykonywanie zapytania dopasowującego przebiega następująco:

Dopóki nie zaszło dopasowanie, dla każdej krotki MatchFunction w liście MatchExpression wykonuj:

  • Dopasuj MatchHead do argumentów funkcji, zwiąż '$<int>' z przekazanymi argumentami. Dopasowanie zawodzi jeśli nie można dopasować MatchHead do argumentów.
  • Oblicz każdy z MatchConditions, ale najpierw zwiąż parametry z dopasowanymi w poprzednim kroku. Warunek uznajemy za spełniony jeśli jego sprawdzenie dało atom true, w przeciwnym wypadku (BIF rzuciło wyjątek, wartość nie będąca true) warunek nie zostaje spełniony.
  • (wariant ets) Oblicz wartość wyrażenia i zwróć jako rezultat zapytania.

Uwaga: Niektóre wyrażenia zachowują się nieintuicyjnie!

Wyrażenie Wiązanie Wynik
{ {'$1','$2'} } '$1' = a, '$2' = b {a,b}
{const, {'$1', '$2'}} {'$1', '$2'}
'$1' '$1' = [] []
['$1'] '$1' = [] [ [] ]
[ { {a} } ] [{a}]

Tłumaczenie funkcji

Całe szczęście nie zawsze trzeba pisać zapytanie dopasowujące samemu. W większości przypadków można użyć modułu zajmujących się tłumaczeniem funkcji na zapytania. Oczywiście tłumaczone funkcje podlegają pewnym ograniczeniom.

Przykładowa funkcja

1> Y=25.
25
2> F = fun({A,B}) when A > Y -> B end.
#Fun<erl_eval.6.13229925>

Tłumaczenie na piechotę

3> {fun_data,ImportList,Clauses} = erl_eval:fun_data(F).
{fun_data,[{'Y',25}],
          [{clause,1,
                   [{tuple,1,[{var,1,'A'},{var,1,'B'}]}],
                   [[op_1_var_1_a_var_1_y]],
                   [{var,1,'B'}]}]}
4> ms_transform:transform_from_shell(ets, Clauses, ImportList).
[{{'$1','$2'},[{'>','$1',{const,25}}],['$2']}]

Tłumaczenie bezpośrednio przy pomocy ets:fun2ms/1

5> ets:fun2ms(F).
[{{'$1','$2'},[{'>','$1',{const,25}}],['$2']}]

Przykłady

1> ets:fun2ms( fun( {A,_,A} = All ) -> All end ).
 
[{{'$1', '_', '$1'},
  [],
  ['$_']}]
2> ets:fun2ms( fun({_,A,_} = All) when A > 3 -> All end ).
 
[{{'_', '$1', '_'},
  [{ '>', '$1', 3}],
  ['$_']}]
3> ets:fun2ms( fun({A,B,C}) when C =:= [A,B] orelse ( A =:= hd(C) ) and ( B =:= hd(tl(C)) ) -> {A,B} end ).
 
[{{'$1','$2','$3'},
  [{'orelse',
    {'=:=','$3',['$1','$2']},
    {'and',
      {'=:=','$1',{hd,'$3'}},
      {'=:=','$2',{hd,{tl,'$3'}}}
    }
  }],
  [{{'$1','$2'}}]}]
4> ets:fun2ms( fun({A,B,{A,B}}) -> {A,B}; ({A,B,[A,B,_]}) -> {A,B} end ).
 
[{{'$1', '$2', {'$1','$2'}}, [], [{{'$1','$2'}}]},
 {{'$1', '$2', ['$1','$2','_']}, [], [{{'$1','$2'}}]}]
5> ets:fun2ms( fun({A, B}) when 2 * B =:= hd(element(1, A)) -> A end ).
 
[{{'$1', '$2'},
  [{'=:=', {'*', 2, '$2'},{hd, {element, 1, '$1'}}}],
  ['$1']}]
6> ets:fun2ms( fun({strider, _, _} = R) -> R end ).
 
[{{strider, '_', '_'},
  [],
  ['$_']}]
7> ets:fun2ms( fun(R) when gandalf == element(1, R), size(R) >= 2 -> element(2, R) end ).
 
[{'$1',
  [{'==', gandalf, {element, 1, '$1'}},{'>=', {size, '$1'},2}],
  [{element, 2, '$1'}]}]
8> ets:fun2ms( fun({_, merry, _} = R) -> R; ({_, pippin, _} = R) -> R end ).
 
[{{'_',merry,'_'},
  [],
  ['$_']},
 {{'_',pippin,'_'},
  [],
  ['$_']}]

Źródła

Podręczniki:

Moduły:

  • ms_transform - przekształcanie funkcji w wyrażenia dopasowujące
 
erlang/database/match_spec.txt · Last modified: 2010/05/25 20:24 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