[erlang-questions] distinguish proplists vs. lists of proplists

Richard A. O'Keefe <>
Wed Sep 16 07:09:35 CEST 2015


On 16/09/2015, at 4:58 am, Mr rty ff <> wrote:
> I write a function which gets proplists or list of proplists anf key.

WHY?

This is just confusing.
Just DON'T.

As you've pointed out, your function does not know its
caller's intent and has to guess.  (Was [] an empty proplist
or an empty list of proplists?)

The caller KNOWS.  Or should know.  So

handle_list_of_proplists(LP) -> ...

handle_proplist(P) -> handle_list_of_proplists([P]).

Trying to put both computations in a single function
is like trying to put both feet into one shoe; succeed
or fail it is going to hurt.

Let's turn to http://www.erlang.org/doc/man/proplists.html
to find out what a proplist is:

  "Property lists are ordinary lists containing entries in
   the form of either tuples, whose first elements are keys
   used for lookup and insertion, or atoms, which work as
   shorthand for tuples {Atom, true}."

Sounds pretty clear.

handle_either_case([]) ->
   your definition had better give the SAME answer
   for empty proplists and empty lists of proplists;
handle_either_case([P|Ps]) when is_list(P) ->
   handle_list_of_proplists([P|Ps]);
handle_either_case(P) ->
   handle_proplist(P).

But wait, there's more:

  "(Other terms are allowed in the lists,
   but are ignored by this module.)"

Oops.  Your task just got impossible.  A list of proplists
*is* a proplist, just one that contains no keys.

The *best* way to do this is NOT to have a single function
do both jobs, but have two functions, and get the *caller*
to figure it out.

The nearest it's possible to get to what you want is to
accept only "strict" proplists:

 - a strict proplist is []
 - or [B|P] where P is a strict proplist and
     + B is an atom (treated as {B,true} or
     + B is a tuple {_,_}.

check_strict_proplist([]) ->
    ok;
check_strict_proplist([B|P]) when is_atom(B) ->
    check_strict_proplist(P);
check_strict_proplist([{_,_}|P]) -
     check_strict_proplist(P)
check_strict_proplist([X|_]) ->
    {bad_element,X};
check_strict_proplist(X) ->
    {non_list,X}.

and use that to decide what you have.

Or you could do something like

get_values_anywhere(Key, Prop_Tree) ->
    get_values_anywhere(Key, Prop_Tree, []).

%% get_values_anywhere(Key, Prop_Tree, Vs) =
%% get_values_anywhere(Key, Prop_Tree) ++ Vs.

get_values_anywhere(Key, [H|T], Vs) ->
    get_values_anywhere(Key, H,
        get_values_anywhere(Key, T, Vs));
get_values_anywhere(Key, {Key,V}, Vs) ->
    [V|Vs];
get_values_anywhere(Key, Key, Vs) ->
    [true|Vs];
get_values_anywhere(_, _, Vs) ->
    Vs.

Note: I said something *LIKE* that.  This code is not tested,
and probably isn't what you want anyway.  I'm pretty confident
it's not what you *need*, because that's not to muddle up the
two things in the first place.





More information about the erlang-questions mailing list