[erlang-questions] Record-like syntax for dictionaries

Andy Kriger <>
Wed Jan 5 15:56:02 CET 2011


That looks great. Is there a way that fetching a non-existent field can
return undefined instead of requiring a catch?

On Wed, Jan 5, 2011 at 4:30 AM, Anton Lavrik <> wrote:

> Hi all,
>
> While playing with Erlang parse transformations, I came up with the
> idea of using a record-like syntax for basic operations with
> dictionaries from stdlib's "dict" module. Dictionary construction and
> accessing elements by keys are conceptually similar to record
> construction and accessing record fields, however standard dictionary
> interface is rather cumbersome compared to Erlang record syntax.
>
> I created a parse transformation to test this idea. This is a usage
> example:
>
> -include_lib("erl_aliases.hrl").
> -dict_alias('').
> dict_alias_test() ->
>    % creating an empty dictionary
>    _ = #{},
>
>    % associating foo with 1
>    D = #{foo = 1},
>    1 = D.foo,
>
>    % setting foo to foo + 1 and baz to 100
>    D1 = D#{foo = D.foo + 1}#{baz = 100},
>    2 = D1.foo,
>    100 = D1.baz,
>
>    % accessing undefined field
>    {'EXIT', {badarg, _}} = (catch D.bar),
>
>    % several elements
>    D2 = D#{bar = 1, fum = 10, obj = D},
>    1 = D2.bar,
>    10 = D2.fum,
>
>    % accessing field of a dict included in another dict
>    1 = D2.obj.foo,
>    ok.
>
> This is the result of the parse transformation:
>
> dict_alias_test() ->
>    _ = dict:new(),
>    D = dict:store(foo, 1, dict:new()),
>    1 = dict:fetch(foo, D),
>    D1 =
>        dict:store(baz, 100, dict:store(foo, dict:fetch(foo, D) + 1, D)),
>    2 = dict:fetch(foo, D1),
>    100 = dict:fetch(baz, D1),
>    {'EXIT',{badarg,_}} = (catch dict:fetch(bar, D)),
>    D2 = dict:store(obj, D, dict:store(fum, 10, dict:store(bar, 1, D))),
>    1 = dict:fetch(bar, D2),
>    10 = dict:fetch(fum, D2),
>    1 = dict:fetch(foo, dict:fetch(obj, D2)),
>    ok.
>
> Note that in the beginning I defined a dict alias for an empty atom:
> -dict_alias(''). If any other non-empty atom is used, then dictionary
> construction and element access look exactly as correspondent record
> operations. For example, with -dict_alias(dict), #dict{} will be
> transformed to dict:new(), X#dict.a -- to dict:fetch(a, X) and so on.
> This was the original idea, but then I discovered that it is possible
> to get rid of record names, i.e. use #{} instead of #dict{} and X.foo
> instead of X#dict.foo, etc. This, however, required definition of
> three extra Yecc rules in erl_parse.yrl to handle expressions like
> #{...}.
>
> Obviously, such parse transformations work only with expressions --
> they are not applied to guards and patterns.
>
> The code is on GitHub (https://github.com/alavrik/erl_aliases), but
> this functionality is not documented yet.
>
> Overall, this looks pretty neat to me. Beyond simple use, I'm
> thinking, for example, about converting arbitrary JSON objects to
> dictionaries and then accessing their contents using this method.
> Parsed JSON object keys can be converted to atoms using
> binary_to_existing_atom.
>
> What do you think? Is there anything I'm missing here that makes such
> parse transformation potentially unreliable?
>
> Anton
>
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:
>
>


-- 
Be well,
andy

Welcome to http://householder-yogi.net
On family, NYC, and practicing yoga.


More information about the erlang-questions mailing list