Why use -record() ?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Why use -record() ?

I Gusti Ngurah Oka Prinarjaya
Hi,


Let's see code below:

-module(ppool_serv).
-behaviour(gen_server).
....
....
-record(state, {limit=0, sup, refs, queue=queue:new()}).
....
....
init({Limit, MFA, Sup}) ->
  self() ! {start_worker_supervisor, Sup, MFA},

  %% why using -record here for state holder?
  {ok, #state{limit=Limit, refs=gb_sets:empty()}}.


From the code above, why using record to hold state?

Other than using record we also can use tuple right? Let's see alternative code below

-module(ppool_serv).
-behaviour(gen_server).
....
....
....
init({Limit, MFA, Sup}) ->
  self() ! {start_worker_supervisor, Sup, MFA},

  Refs = gb_sets:empty(),
  Queue = queue:new(),
  Spv = undefined,
  State = {Limit, Spv, Refs, Queue},

  {ok, State}.
...
...
...
handle_call({run, Args}, _From, {Limit, Spv, Refs, Queue}) when N > 0 ->
  {ok, Pid} = supervisor:start_child(Spv, Args),
  Ref = erlang:monitor(process, Pid),
  NewRefs = gb_sets:add(Ref, Refs),
  NewState = {Limit-1, Spv, NewRefs, Queue},
  {reply, {ok, Pid}, NewState};


We also can use the above alternative code right?

Please enlightenment 


Thank you 







_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Why use -record() ?

Stefan Hellkvist-2

...
handle_call({run, Args}, _From, {Limit, Spv, Refs, Queue}) when N > 0 ->
  {ok, Pid} = supervisor:start_child(Spv, Args),
  Ref = erlang:monitor(process, Pid),
  NewRefs = gb_sets:add(Ref, Refs),
  NewState = {Limit-1, Spv, NewRefs, Queue},
  {reply, {ok, Pid}, NewState};


We also can use the above alternative code right?

Yes, you can use whatever Erlang term you prefer - record, tuple, map, a list of maps containing records of tuples...

What you choose is a matter of taste and depends on your requirements. A record for instance has the advantage over a tuple, that you access elements by name and the order of elements therefore becomes irrelevant. This could give advantages if you one day decide to add another field to your state. With the tuple approach this would likely break every access to the tuple everywhere in the code, but with a record where you access and match by names most of your code might still work...plus you never need to remember what meaning the third or fourth element in your tuple has l, because it has a descriptive name.

Stefan 

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Why use -record() ?

Jack Tang
In reply to this post by I Gusti Ngurah Oka Prinarjaya
Yes, `state` can be any data structure of erlang, and `record` is another form of `tuple`. `-record(state....` equals to `{state, ....}`
I prefer record to tuple in some cases because the element can be matched/retrieved without considering the order. the example:

`#state{refs = Refs} = State`, 

do the same thing using tuple, you should take care of the order and must fully matched

{_, _, Ref, _, _} = State

-Jack

On Sun, Jun 2, 2019 at 6:25 PM I Gusti Ngurah Oka Prinarjaya <[hidden email]> wrote:
Hi,


Let's see code below:

-module(ppool_serv).
-behaviour(gen_server).
....
....
-record(state, {limit=0, sup, refs, queue=queue:new()}).
....
....
init({Limit, MFA, Sup}) ->
  self() ! {start_worker_supervisor, Sup, MFA},

  %% why using -record here for state holder?
  {ok, #state{limit=Limit, refs=gb_sets:empty()}}.


From the code above, why using record to hold state?

Other than using record we also can use tuple right? Let's see alternative code below

-module(ppool_serv).
-behaviour(gen_server).
....
....
....
init({Limit, MFA, Sup}) ->
  self() ! {start_worker_supervisor, Sup, MFA},

  Refs = gb_sets:empty(),
  Queue = queue:new(),
  Spv = undefined,
  State = {Limit, Spv, Refs, Queue},

  {ok, State}.
...
...
...
handle_call({run, Args}, _From, {Limit, Spv, Refs, Queue}) when N > 0 ->
  {ok, Pid} = supervisor:start_child(Spv, Args),
  Ref = erlang:monitor(process, Pid),
  NewRefs = gb_sets:add(Ref, Refs),
  NewState = {Limit-1, Spv, NewRefs, Queue},
  {reply, {ok, Pid}, NewState};


We also can use the above alternative code right?

Please enlightenment 


Thank you 






_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


--

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Why use -record() ?

bengt e
In reply to this post by Stefan Hellkvist-2
Greetings,

It is true that it is a matter of taste but remember that some Erlang containers can not be used to pattern match. Using one of those handle_call/3 would only be one function clause. And while maps can be pattern matched the compiler will not help you with spelling mistakes, as it does with records.


Best Wishes,
bengt

On 2 Jun 2019, at 13:25, Stefan Hellkvist <[hidden email]> wrote:


...
handle_call({run, Args}, _From, {Limit, Spv, Refs, Queue}) when N > 0 ->
  {ok, Pid} = supervisor:start_child(Spv, Args),
  Ref = erlang:monitor(process, Pid),
  NewRefs = gb_sets:add(Ref, Refs),
  NewState = {Limit-1, Spv, NewRefs, Queue},
  {reply, {ok, Pid}, NewState};


We also can use the above alternative code right?

Yes, you can use whatever Erlang term you prefer - record, tuple, map, a list of maps containing records of tuples...

What you choose is a matter of taste and depends on your requirements. A record for instance has the advantage over a tuple, that you access elements by name and the order of elements therefore becomes irrelevant. This could give advantages if you one day decide to add another field to your state. With the tuple approach this would likely break every access to the tuple everywhere in the code, but with a record where you access and match by names most of your code might still work...plus you never need to remember what meaning the third or fourth element in your tuple has l, because it has a descriptive name.

Stefan 
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Why use -record() ?

Dmitry Kolesnikov-2
Hello,

There was quite good reasoning already about records. I just want to make a quotation from my resent post about records. I hope it helps you to catch the reason why…

Type theory and a functional programming operates with [algebraic data types](https://en.wikipedia.org/wiki/Algebraic_data_type). They are known as a composition of other types. The theory defines two classes of compositions: product types (tuples, records) and co-product types (sum, enumeration or variant types). Product types are strongly expressed by [records](http://erlang.org/doc/reference_manual/records.html) in Erlang. 

```erlang
-type fullname() :: binary().
-type address()  :: binary().
-type city()     :: binary().

-record(person, {
   name    :: fullname(),
   address :: address(), 
   city    :: city()
}).
```

The beauty of Erlang records (product type) is that they definitions are only available at compile time. The compiler has complete knowledge of defined "algebra" and catches misuse errors. The usage of records in your code benefits to write correct, maintainable code and support refactoring. Use them to define your domain models!

```erlang
#person{birthday = "18810509"}.

%% Compiling src/person.erl failed
%% src/person.erl:18: field birthday undefined in record person
```

There are few other benefits of records over other data types: type testing and pattern matching. These subject has been widely covered at [official documentation](http://erlang.org/doc/programming_examples/records.html):

```erlang
%%
%% type testing
myfun(X) when is_record(X, person) -> ...

%%
%% pattern matching
myfun(#person{name = Name}) -> ...
``` 

As a summary, I would strongly advertise the usage of records to reflect your domain. Other types will work too...

Best Regards,
Dmitry

On 2 Jun 2019, at 14.34, bengt <[hidden email]> wrote:

Greetings,

It is true that it is a matter of taste but remember that some Erlang containers can not be used to pattern match. Using one of those handle_call/3 would only be one function clause. And while maps can be pattern matched the compiler will not help you with spelling mistakes, as it does with records.


Best Wishes,
bengt

On 2 Jun 2019, at 13:25, Stefan Hellkvist <[hidden email]> wrote:


...
handle_call({run, Args}, _From, {Limit, Spv, Refs, Queue}) when N > 0 ->
  {ok, Pid} = supervisor:start_child(Spv, Args),
  Ref = erlang:monitor(process, Pid),
  NewRefs = gb_sets:add(Ref, Refs),
  NewState = {Limit-1, Spv, NewRefs, Queue},
  {reply, {ok, Pid}, NewState};


We also can use the above alternative code right?

Yes, you can use whatever Erlang term you prefer - record, tuple, map, a list of maps containing records of tuples...

What you choose is a matter of taste and depends on your requirements. A record for instance has the advantage over a tuple, that you access elements by name and the order of elements therefore becomes irrelevant. This could give advantages if you one day decide to add another field to your state. With the tuple approach this would likely break every access to the tuple everywhere in the code, but with a record where you access and match by names most of your code might still work...plus you never need to remember what meaning the third or fourth element in your tuple has l, because it has a descriptive name.

Stefan 
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Why use -record() ?

I Gusti Ngurah Oka Prinarjaya
Hi,

Thank you for all of you guys. It's very very clear now. Wow.. very enlightening! thank you.

The key is:
Using tuple will ruin your life when you need to add a new element in your state. Because tuple do really really need to match the order of elements. Because yes i absolutely  lazy to remember the order of tuple's elements.

Thank you for the additional knowledge about type theory algebra data types, it's a new knowledge for me. 




Pada tanggal Min, 2 Jun 2019 pukul 18.57 Dmitry Kolesnikov <[hidden email]> menulis:
Hello,

There was quite good reasoning already about records. I just want to make a quotation from my resent post about records. I hope it helps you to catch the reason why…

Type theory and a functional programming operates with [algebraic data types](https://en.wikipedia.org/wiki/Algebraic_data_type). They are known as a composition of other types. The theory defines two classes of compositions: product types (tuples, records) and co-product types (sum, enumeration or variant types). Product types are strongly expressed by [records](http://erlang.org/doc/reference_manual/records.html) in Erlang. 

```erlang
-type fullname() :: binary().
-type address()  :: binary().
-type city()     :: binary().

-record(person, {
   name    :: fullname(),
   address :: address(), 
   city    :: city()
}).
```

The beauty of Erlang records (product type) is that they definitions are only available at compile time. The compiler has complete knowledge of defined "algebra" and catches misuse errors. The usage of records in your code benefits to write correct, maintainable code and support refactoring. Use them to define your domain models!

```erlang
#person{birthday = "18810509"}.

%% Compiling src/person.erl failed
%% src/person.erl:18: field birthday undefined in record person
```

There are few other benefits of records over other data types: type testing and pattern matching. These subject has been widely covered at [official documentation](http://erlang.org/doc/programming_examples/records.html):

```erlang
%%
%% type testing
myfun(X) when is_record(X, person) -> ...

%%
%% pattern matching
myfun(#person{name = Name}) -> ...
``` 

As a summary, I would strongly advertise the usage of records to reflect your domain. Other types will work too...

Best Regards,
Dmitry

On 2 Jun 2019, at 14.34, bengt <[hidden email]> wrote:

Greetings,

It is true that it is a matter of taste but remember that some Erlang containers can not be used to pattern match. Using one of those handle_call/3 would only be one function clause. And while maps can be pattern matched the compiler will not help you with spelling mistakes, as it does with records.


Best Wishes,
bengt

On 2 Jun 2019, at 13:25, Stefan Hellkvist <[hidden email]> wrote:


...
handle_call({run, Args}, _From, {Limit, Spv, Refs, Queue}) when N > 0 ->
  {ok, Pid} = supervisor:start_child(Spv, Args),
  Ref = erlang:monitor(process, Pid),
  NewRefs = gb_sets:add(Ref, Refs),
  NewState = {Limit-1, Spv, NewRefs, Queue},
  {reply, {ok, Pid}, NewState};


We also can use the above alternative code right?

Yes, you can use whatever Erlang term you prefer - record, tuple, map, a list of maps containing records of tuples...

What you choose is a matter of taste and depends on your requirements. A record for instance has the advantage over a tuple, that you access elements by name and the order of elements therefore becomes irrelevant. This could give advantages if you one day decide to add another field to your state. With the tuple approach this would likely break every access to the tuple everywhere in the code, but with a record where you access and match by names most of your code might still work...plus you never need to remember what meaning the third or fourth element in your tuple has l, because it has a descriptive name.

Stefan 
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Why use -record() ?

t ty
I recommend using record for a very different reason and not in the form you showed in your example.

My recommendation is to prefix the module name to the record. e.g

```
-module(ppool_serv).

-record(ppool_serv_state, ...).
```

My reasoning is during an error report having just a list or tuple or map would result in an unintelligible data structure displayed. With a record, as above, you can determine at a quick glance the record in question. It is also easier to determine the attributes in the record in this manner.

Cheers



On Sun, Jun 2, 2019 at 2:24 PM I Gusti Ngurah Oka Prinarjaya <[hidden email]> wrote:
Hi,

Thank you for all of you guys. It's very very clear now. Wow.. very enlightening! thank you.

The key is:
Using tuple will ruin your life when you need to add a new element in your state. Because tuple do really really need to match the order of elements. Because yes i absolutely  lazy to remember the order of tuple's elements.

Thank you for the additional knowledge about type theory algebra data types, it's a new knowledge for me. 




Pada tanggal Min, 2 Jun 2019 pukul 18.57 Dmitry Kolesnikov <[hidden email]> menulis:
Hello,

There was quite good reasoning already about records. I just want to make a quotation from my resent post about records. I hope it helps you to catch the reason why…

Type theory and a functional programming operates with [algebraic data types](https://en.wikipedia.org/wiki/Algebraic_data_type). They are known as a composition of other types. The theory defines two classes of compositions: product types (tuples, records) and co-product types (sum, enumeration or variant types). Product types are strongly expressed by [records](http://erlang.org/doc/reference_manual/records.html) in Erlang. 

```erlang
-type fullname() :: binary().
-type address()  :: binary().
-type city()     :: binary().

-record(person, {
   name    :: fullname(),
   address :: address(), 
   city    :: city()
}).
```

The beauty of Erlang records (product type) is that they definitions are only available at compile time. The compiler has complete knowledge of defined "algebra" and catches misuse errors. The usage of records in your code benefits to write correct, maintainable code and support refactoring. Use them to define your domain models!

```erlang
#person{birthday = "18810509"}.

%% Compiling src/person.erl failed
%% src/person.erl:18: field birthday undefined in record person
```

There are few other benefits of records over other data types: type testing and pattern matching. These subject has been widely covered at [official documentation](http://erlang.org/doc/programming_examples/records.html):

```erlang
%%
%% type testing
myfun(X) when is_record(X, person) -> ...

%%
%% pattern matching
myfun(#person{name = Name}) -> ...
``` 

As a summary, I would strongly advertise the usage of records to reflect your domain. Other types will work too...

Best Regards,
Dmitry

On 2 Jun 2019, at 14.34, bengt <[hidden email]> wrote:

Greetings,

It is true that it is a matter of taste but remember that some Erlang containers can not be used to pattern match. Using one of those handle_call/3 would only be one function clause. And while maps can be pattern matched the compiler will not help you with spelling mistakes, as it does with records.


Best Wishes,
bengt

On 2 Jun 2019, at 13:25, Stefan Hellkvist <[hidden email]> wrote:


...
handle_call({run, Args}, _From, {Limit, Spv, Refs, Queue}) when N > 0 ->
  {ok, Pid} = supervisor:start_child(Spv, Args),
  Ref = erlang:monitor(process, Pid),
  NewRefs = gb_sets:add(Ref, Refs),
  NewState = {Limit-1, Spv, NewRefs, Queue},
  {reply, {ok, Pid}, NewState};


We also can use the above alternative code right?

Yes, you can use whatever Erlang term you prefer - record, tuple, map, a list of maps containing records of tuples...

What you choose is a matter of taste and depends on your requirements. A record for instance has the advantage over a tuple, that you access elements by name and the order of elements therefore becomes irrelevant. This could give advantages if you one day decide to add another field to your state. With the tuple approach this would likely break every access to the tuple everywhere in the code, but with a record where you access and match by names most of your code might still work...plus you never need to remember what meaning the third or fourth element in your tuple has l, because it has a descriptive name.

Stefan 
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Why use -record() ?

dieter
That's a good one, thank you for sharing!

dieter



Am So., Jun. 2, 2019 20:34 schrieb T Ty <[hidden email]>:
I recommend using record for a very different reason and not in the form you showed in your example.

My recommendation is to prefix the module name to the record. e.g

```
-module(ppool_serv).

-record(ppool_serv_state, ...).
```

My reasoning is during an error report having just a list or tuple or map would result in an unintelligible data structure displayed. With a record, as above, you can determine at a quick glance the record in question. It is also easier to determine the attributes in the record in this manner.

Cheers



On Sun, Jun 2, 2019 at 2:24 PM I Gusti Ngurah Oka Prinarjaya <[hidden email]> wrote:
Hi,

Thank you for all of you guys. It's very very clear now. Wow.. very enlightening! thank you.

The key is:
Using tuple will ruin your life when you need to add a new element in your state. Because tuple do really really need to match the order of elements. Because yes i absolutely  lazy to remember the order of tuple's elements.

Thank you for the additional knowledge about type theory algebra data types, it's a new knowledge for me. 




Pada tanggal Min, 2 Jun 2019 pukul 18.57 Dmitry Kolesnikov <[hidden email]> menulis:
Hello,

There was quite good reasoning already about records. I just want to make a quotation from my resent post about records. I hope it helps you to catch the reason why…

Type theory and a functional programming operates with [algebraic data types](https://en.wikipedia.org/wiki/Algebraic_data_type). They are known as a composition of other types. The theory defines two classes of compositions: product types (tuples, records) and co-product types (sum, enumeration or variant types). Product types are strongly expressed by [records](http://erlang.org/doc/reference_manual/records.html) in Erlang. 

```erlang
-type fullname() :: binary().
-type address()  :: binary().
-type city()     :: binary().

-record(person, {
   name    :: fullname(),
   address :: address(), 
   city    :: city()
}).
```

The beauty of Erlang records (product type) is that they definitions are only available at compile time. The compiler has complete knowledge of defined "algebra" and catches misuse errors. The usage of records in your code benefits to write correct, maintainable code and support refactoring. Use them to define your domain models!

```erlang
#person{birthday = "18810509"}.

%% Compiling src/person.erl failed
%% src/person.erl:18: field birthday undefined in record person
```

There are few other benefits of records over other data types: type testing and pattern matching. These subject has been widely covered at [official documentation](http://erlang.org/doc/programming_examples/records.html):

```erlang
%%
%% type testing
myfun(X) when is_record(X, person) -> ...

%%
%% pattern matching
myfun(#person{name = Name}) -> ...
``` 

As a summary, I would strongly advertise the usage of records to reflect your domain. Other types will work too...

Best Regards,
Dmitry

On 2 Jun 2019, at 14.34, bengt <[hidden email]> wrote:

Greetings,

It is true that it is a matter of taste but remember that some Erlang containers can not be used to pattern match. Using one of those handle_call/3 would only be one function clause. And while maps can be pattern matched the compiler will not help you with spelling mistakes, as it does with records.


Best Wishes,
bengt

On 2 Jun 2019, at 13:25, Stefan Hellkvist <[hidden email]> wrote:


...
handle_call({run, Args}, _From, {Limit, Spv, Refs, Queue}) when N > 0 ->
  {ok, Pid} = supervisor:start_child(Spv, Args),
  Ref = erlang:monitor(process, Pid),
  NewRefs = gb_sets:add(Ref, Refs),
  NewState = {Limit-1, Spv, NewRefs, Queue},
  {reply, {ok, Pid}, NewState};


We also can use the above alternative code right?

Yes, you can use whatever Erlang term you prefer - record, tuple, map, a list of maps containing records of tuples...

What you choose is a matter of taste and depends on your requirements. A record for instance has the advantage over a tuple, that you access elements by name and the order of elements therefore becomes irrelevant. This could give advantages if you one day decide to add another field to your state. With the tuple approach this would likely break every access to the tuple everywhere in the code, but with a record where you access and match by names most of your code might still work...plus you never need to remember what meaning the third or fourth element in your tuple has l, because it has a descriptive name.

Stefan 
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Why use -record() ?

Krzysztof Jurewicz
In reply to this post by Dmitry Kolesnikov-2
> There are few other benefits of records over other data types: type testing and pattern matching. These subject has been widely covered at [official documentation](http://erlang.org/doc/programming_examples/records.html):
>
> ```erlang
> %%
> %% type testing
> myfun(X) when is_record(X, person) -> ...

It is however worth to mention that “type testing” of records doesn’t actually perform type testing of record fields. is_record(X, person) checks only that X is a tuple of correct size and that its first element is 'person'. Therefore is_record(#person{name=foo}, person) will return true despite the name field being type annotated as binary. Dialyzer too wil not always catch type errors in record construction.
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions