Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty Map Pattern matches even for non-empty Map

Tags:

erlang

The problem I am trying to solve states

Write a function map_search_pred(Map, Pred) that returns the first element {Key,Value} in the map for which Pred(Key, Value) is true.

My attempt looks like

map_search_pred(#{}, _)     -> {};
map_search_pred(Map, Pred)  ->
  [H|_] = [{Key, Value} || {Key, Value} <- maps:to_list(Map), Pred(Key, Value) =:= true],
  H.

When I run this, I see output as

1> lib_misc:map_search_pred(#{1 => 1, 2 => 3}, fun(X, Y) -> X =:= Y end).
{}
2> lib_misc:map_search_pred(#{1 => 1, 2 => 3}, fun(X, Y) -> X =:= Y end).
{}
3> maps:size(#{}).
0
4> 

How am I so sure? I pulled out the first clause so it looks like

map_search_pred(Map, Pred)  ->
  [H|_] = [{Key, Value} || {Key, Value} <- maps:to_list(Map), Pred(Key, Value) =:= true],
  H.

and run again

1> lib_misc:map_search_pred(#{1 => 1, 2 => 3}, fun(X, Y) -> X =:= Y end).
{1,1}
2> lib_misc:map_search_pred(#{}, fun(X, Y) -> X =:= Y end).
** exception error: no match of right hand side value []
     in function  lib_misc:map_search_pred/2 (/Users/harith/code/IdeaProjects/others/erlang/programmingErlang/src/lib_misc.erl, line 42)
3>
like image 664
daydreamer Avatar asked Jan 07 '15 22:01

daydreamer


1 Answers

According to map documentation:

Matching an expression against an empty map literal will match its type but no variables will be bound:

#{} = Expr

This expression will match if the expression Expr is of type map, otherwise it will fail with an exception badmatch.

However erlang:map_size can be used instead:

map_search_pred(Map, _) when map_size(Map) == 0 ->
  {};
map_search_pred(Map, Pred) ->
  [H|_] = [{Key, Value} || {Key, Value} <- maps:to_list(Map), Pred(Key, Value) =:= true],
  H.
like image 102
Ed'ka Avatar answered Oct 21 '22 09:10

Ed'ka