[erlang-questions] Record-like syntax for dictionaries
Andy Kriger
andy.kriger@REDACTED
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 <alavrik@REDACTED> 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:erlang-questions-unsubscribe@REDACTED
>
>
--
Be well,
andy
Welcome to http://householder-yogi.net
On family, NYC, and practicing yoga.
More information about the erlang-questions
mailing list