[erlang-questions] New module syntax and semantics?
Richard A. O'Keefe
ok@REDACTED
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