[erlang-questions] New module syntax and semantics?

Richard A. O'Keefe <>
Fri Jul 4 06:50:50 CEST 2008


On 3 Jul 2008, at 10:13 am, Juan Jose Comellas wrote:
> Nested records are not nice, no. For the record:
>
> make_stuff() ->
>   
> #fs_channel_event 
> {extra=#fs_channel_answer_event{write_codec_name=rot13}}.

Let's tidy this a bit:

make_stuff() ->
     Extra = #fs_channel_answer_event{write_codec_name = rot13},
     #fs_channel_event{extra = Extra}.

The thing that makes this tricky to read is that the detail is
hidden amongst the other stuff.  So define a function:

fs_channel_answer_with_write_codec(Write_Codec_Name) ->
     #fs_channel_event{
         extra = #fs_channel_answer_event{
             write_codec_name = Write_Codec_Name}}.

and make_stuff() becomes

make_stuff() ->
     fs_channel_answer_with_write_codec(rot13).

> set_stuff(Ex) ->
>  Ex2 =  
> Ex 
> #fs_channel_event 
> {extra 
> = 
> (Ex 
> #fs_channel_event 
> .extra)#fs_channel_answer_event{read_codec_name=leetspeak}}.


Let's tidy that a bit again.

set_stuff(Event = #fs_channel_event{extra = Extra}) ->
     Extra1 = Extra#fs_channel_answer_event{read_codec_name =  
leetspeak},
     Event#fs_channel_event{extra = Extra1}.

It's not the nested *records* that are the problem,
but the nested *expressions*.
Oh, and the sheer length of Erlang field references,
due to the need to include the record name as well as
the field name.  Again, I'd define a function

set_fs_channel_answer_read_codec(
     Event = #fs_channel_event{extra = Extra},
     Read_Codec_Name
) ->
     Event#fs_channel_event{
         extra = Extra#fs_channel_answer_event{
             read_codec_name = Read_Codec_Name}}.

set_stuff(Event) ->
     set_fs_channel_answer_read_codec(Event, leetspeak).

With abstract patterns, you could be defining "records" that
happened to be nested *tuples*, but with they'd be treated
in the source code as flat.

> Did you consider using an approach like the following instead?
>
> AnswerEvent = {#fs_channel_event{}, #fs_answer_event{}}
> HangupEvent = {#fs_channel_event{}, #fs_hangup_event{}}
>
> It's easy to deconstruct a tuple in pattern matching. You dont get the
> nesting above.
>
> make_stuff() ->
>  {#fs_channel_event{},  
> #fs_channel_answer_event{write_codec_name=rot13}}.
> set_stuff({A, B}) ->
>   {A, B#fs_channel_answer_event{read_codec_name=leetspeak}}.

You _do_ get nesting, it's just that the outer record is anonymous.
I'm not saying it's a bad thing or a bad idea, but it's important to
keep the difference between eliminating nesting *structures* and
eliminating nested *names* straight.

What's really needed here is not parametric modules but
abstract patterns.






More information about the erlang-questions mailing list