Erlang - pattern matching predicate - erlang

To know if particular expression matches specified pattern I can write in erlang something like following:
case <expression> of
<pattern> -> true;
_ -> false
end
For example:
case {1, 2, 3} of
{_, 2, _} -> true;
_ -> false
end
Is there a way to write it in more compact way? Something like:
is_match(<pattern>, <expression>)

No, there's no such construct. You could define a macro to do it:
-define(is_match(Pattern, Expr), case Expr of Pattern -> true; _ -> false end).

another macro :o) -define (IS_MATCH(PAT,EXP), catch(PAT = EXP) == EXP end). with no case, but I am not sure that a catch is better.

Related

Erlang - Searching for tuples within tuples

Using Erlang, I have the following expression:
{add,{var,a},{mul,{num,2},{var,b}}}
and I am using lists:keymember to see whether the letter b is within the expression as such:
lists:keymember(b,2,[expr])
However, it doesn't look within the third tuple '{mul,{num,2},{var,b}' as that is a separate tuple. Is there a function that will search through the whole tuple and tuples within?
Thanks
As far I as I know there are no such functions. Probably you will have to implement some custom solution using recursion. Here is my example:
-module(test).
-compile(export_all).
find(_, []) -> false;
find(E, T) when is_tuple(T) ->
find(E, tuple_to_list(T));
find(E, [H|T]) ->
case find(E, H) of
false -> find(E, T);
true -> true
end;
find(V, E) -> V == E.
And usage:
1> test:find(b, {add,{var,a},{mul,{num,2},{var,b}}}).
true
2> test:find(b, {add,{var,a},{mul,{num,2},{var,c}}}).
false
Please review your code.
Line1: this is a tree, not a list.
Line2: expr is not a variable.
What you want to do is a visitor function, and you'll have to write it yourself.
A very good start would be to read this.

Racket ormap in erlang

Is there a better way to implement Racket's ormap in Erlang than:
ormap(_, []) -> false;
ormap(Pred, [H|T]) ->
case Pred(H) of
false -> ormap(Pred, T);
_ -> {ok, Pred(H)}
end.
Looks pretty good to me. I'm not sure how smart Erlang is about optimizing these things, but you might want to actually bind the non-false pattern match to a variable, and avoid recomputing Pred(H).
ormap(_, []) -> false;
ormap(Pred, [H|T]) ->
case Pred(H) of
false -> ormap(Pred, T);
V -> {ok, V}
end.
The Racket version doesn't include the ok symbol, but that seems like the Erlangy thing to do so I don't see anything wrong with it. You might similarly expect Pred to return an attached ok symbol for the non-false case, in which case:
V -> V
or
{ok, V} -> {ok, V}
should work.

Matching tuples with don't-care variables in Erlang

I am looking for a way to find tuples in a list in Erlang using a partial tuple, similarly to functors matching in Prolog. For example, I would like to following code to return true:
member({pos, _, _}, [..., {pos, 1, 2}, ...])
This code does not work right away because of the following error:
variable '_' is unbound
Is there a brief way to achieve the same effect?
For simple cases it's better to use already mentioned lists:keymember/3. But if you really need member function you can implement it yourself like this:
member(_, []) ->
false;
member(Pred, [E | List]) ->
case Pred(E) of
true ->
true;
false ->
member(Pred, List)
end.
Example:
>>> member(fun ({pos, _, 2}) -> true; (_) -> false end, [..., {pos, 1, 2}, ...]).
Use lists:keymember/3 instead.
You can do it with a macro using a list comprehension:
-define(member(A,B), length([0 || A <- B])>0).
?member({pos, _, _}, [{width, 17, 42}, {pos, 1, 2}, totally_irrelevant]).
It is not very efficient (it runs through the whole list) but it is the closest I can think to the original syntax.
If you want to actually extract the elements that match you just remove 'length' and add a variable:
-define(filter(A,B), [_E || A =_E <- B]).
You could do it using list comprehension:
Matches = [ Match || {Prefix, _, _} = Match <- ZeList, Prefix == pos].
Another possibility would be to do what match specs do and use the atom '_' instead of a raw _. Then, you could write a function similar to the following:
member(X, List) when is_tuple(X), is_list(List) ->
member2(X, List).
% non-exported helper functions:
member2(_, []) ->
false;
member2(X, [H|T]) when not is_tuple(H); size(X) =/= size(H) ->
member2(X, T);
member2(X, [H|T]) ->
case is_match(tuple_to_list(X), tuple_to_list(H)) of
true -> true;
false -> member2(X, T)
end.
is_match([], []) ->
true;
is_match(['_'|T1], [_|T2]) ->
is_match(T1, T2);
is_match([H|T1], [H|T2]) ->
is_match(T1, T2);
is_match(_, _) ->
false.
Then, your call would now be:
member({pos, '_', '_'}, [..., {pos, 1, 2}, ...])
This wouldn't let you match patterns like {A, A, '_'} (checking where the first two elements are identical), but if you don't need variables this should work.
You could also extend it to use variables using a similar syntax to match specs ('$1', '$2', etc) with a bit more work -- add a third parameter to is_match with the variable bindings you've seen so far, then write function clauses for them similar to the clause for '_'.
Granted, this won't be the fastest method. With the caveat that I haven't actually measured, I expect using the pattern matching in the language using a fun will give much better performance, although it does make the call site a bit more verbose. It's a trade-off you'll have to consider.
May use ets:match:
6> ets:match(T, '$1'). % Matches every object in the table
[[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]]
7> ets:match(T, {'_',dog,'$1'}).
[[7],[5]]
8> ets:match(T, {'_',cow,'$1'}).
[]

F# pattern matching when mixing DU's and other values

What would be the most effective way to express the following code?
match cond.EvalBool() with
| true ->
match body.Eval() with
| :? ControlFlowModifier as e ->
match e with
| Break(scope) -> e :> obj //Break is a DU element of ControlFlowModifier
| _ -> next() //other members of CFM should call next()
| _ -> next() //all other values should call next()
| false -> null
cond.EvalBool returns a boolean result where false should return null
and true should either run the entire block again (its wrapped in a func called next)
or if the special value of break is found, then the loop should exit and return the break value.
Is there any way to compress that block of code to something smaller?
I think that the code that you have written is fine. Here's an alternative which I marginally prefer:
let isBreak = function | Break(_) -> true | _ -> false
if cond.EvalBool() then
match body.Eval() with
| :? ControlFlowModifier as e when isBreak e -> e :> obj
| _ -> next()
else
null
I want to point out that it appears there's a subtype hierarchy for the result type of Eval, and if instead that were also a DU, then you could do something like
match body.Eval() with
| ControlFlowModifier(Break e) -> box e
| _ -> next()
Hurray for nested patterns.
I'm not too fond of matching booleans instead of using if-else. What about
let isBreak = function Break _ -> true | _ -> false
...
if cond.EvalBool() then
match body.Eval() with
| :? ControlFlowModifier as e when isBreak e -> box e
| _ -> next()
else null
Or, if you think that special isBreak function shouldn't be necessary (I'd understand that), lets try creating a more general function: C#'s as operator
let tryCast<'T> (o : obj) =
match o with
| :? 'T as x -> Some x
| _ -> None
...
if cond.EvalBool() then
match body.Eval() |> tryCast with
| Some (Break _ as e) -> box e //Break is a DU element of ControlFlowModifier
| _ -> next() //all other values should call next()
else null
I ended up creating an active pattern for this.
Similar logic exist elsewhere so I could make it reusable
let rec next() : obj =
if cond.EvalBool() then
match body.Eval() with
| IsBreak(res) -> res
| _ -> step.Eval() |> ignore ; next()
else null
Looks decent?
To flatten the nested match constructs, you'll need to use nested patterns. This works best for discriminated unions (as pointed out by Brian - and I agree that designing F# code to use primarily discriminated unions is the best thing you can do).
Otherwise, you'll need some active patterns if you want to write the code succinctly using match (ssp posted one example, which shows active patterns specifically for your problem). However, you can do this using the following two reusable active patterns:
let (|TryCast|_|) a : 'res option =
match (box a) with
| :? 'res as r -> Some(r)
| _ -> None
let (|Value|) (l:Lazy<_>) = l.Value
The first one is like :?, but it allows you to nest other patterns to match the value (which isn't possible with as). The second one forces evaluation of lazy value (I suppose that both of them could be declared in F# libraries as they are quite useful). Now you can write:
match lazy cond.EvalBool(), lazy body.Eval() with
| Value(true), Value(TryCast((Break(scope) : ControlFlowModifier)) as e) ->
e :> obj //Break is a DU element of ControlFlowModifier
| Value(true), _ ->
next() //all other values should call next()
| _, _ -> null
EDIT: As Roger pointed out in a comment, this version of the code may not be very readable. I think a better option would be to use only TryCast and format your original code slightly differently (although this isn't completely standard indentation, it is correct and F# compiler handles it fine):
match cond.EvalBool() with
| false -> null
| true ->
match body.Eval() with
| TryCast(Break(scope) as e) -> e :> obj
| _ -> next()
This is probably the most readable option based on pattern matching, but you could also use if instad of the first match as in the version by kvb and combine it with TryCast (this really depends on personal preferences):
if cond.EvalBool() then
match body.Eval() with
| TryCast(Break(scope) as e) -> e :> obj
| _ -> next()
else null
In any case, I believe that TryCast makes the code more readable as you avoid one nesting (which is othervise required because of :? .. as ..).
In case you mean "most effective way" as shortest code, i vote to AP too:
let (|CondEval|_|) (c,_) = if c.EvalBool() then Some true else None
let (|BodyEval|_|) (_,b) =
match b.Eval() with
| ControlFlowModifier as e -> Some e
| _ -> None
match cond,body with
| CondEval _ & BodyEval e -> e :> obj
| true -> next()
| false -> null

Case issue in erlang

Working with Erlang's case, I'm facing a problem. The problem is the following:
other languages:
switch(A)
{
case "A" : case "B" :
//do something
break;
}
So, how to achieve the same thing using Erlang? Because sometimes it is very important to put conditions like these, to avoid overhead.
May be guards are what you want.
the_answer_is(N) when A == "A"; A == "B";
; - is OR
, - is AND
You can use case expressions in Erlang. The syntax is:
case Expression of
Pattern1 [when Guard1] -> Expr_seq1;
Pattern2 [when Guard2] -> Expr_seq2;
...
end
To quote Pragmatic Erlang:
case is evaluated as follows. First,
Expression is evaluated; assume this
evaluates to Value. Thereafter, Value
is matched in turn against Pattern1
(with the optional guard Guard1),
Pattern2, and so on, until a match is
found. As soon as a match is found,
then the corresponding expression
sequence is evaluated—the result of
evaluating the expression sequence is
the value of the case expression. If
none of the patterns match, then an
exception is raised.
An example:
filter(P, [H|T]) ->
case P(H) of
true -> [H|filter(P, T)];
false -> filter(P, T)
end;
filter(P, []) ->
[].
filter(P , L); returns a list of all those elements X in L for which P(X) is true. This can be written using pattern matching, but the case construct makes the code cleaner. Note that choosing between pattern matching and case expressions is a matter of taste, style and experience.
Not my favorite style, but you can do something like:
case A of
_ when A == "A";
A == "B" -> do_ab();
_ when A == "C";
_ when A == "D" -> do_cd();
_ -> do_default()
end.

Resources