Proposing Tuple.deftuple(p)/2, complementary to existing Record.defrecord(p)/3

73 views
Skip to first unread message

Waldemar Rachwał

unread,
Nov 4, 2016, 8:19:19 AM11/4/16
to elixir-l...@googlegroups.com
Hello,

The rationale behind the proposal is the fact there are cases the records can be inappropriate. They provide excellent interface, but well, sometimes the tag atom at first position (index 0) rather harms than helps.

One such use case I found when dealing with ETS tables.

ETS entries are tuples. While entries are homogenic, one record definition which tuple data looks like {:tag, key, field1, ...} seems to be a good fit and only one has to tell ETS the key is at second position (index 1).

However, when it comes to store many tuples of different shapes in one table, the key itself should differentiate these shapes and the instance within given shape, something like {:tag, key}, and then the alone :tag field of a record becomes quite redundant. In such heterogenic ETS tables, existing records have also their own use: for example to hold singular entries each with "global" counters as fields.

Obviously, this is the real use case I encountered. Perhaps there are others. I have no doubt that generally records, in cases one wants to use tuples via functional interface, will be default practice.

I have code ready because I used the stuff earlier from an auxiliary module. In Elixir the Tuple module and deftuple(p) seem natural, but I was never good at naming things...

What do you think?

José Valim

unread,
Nov 4, 2016, 8:21:48 AM11/4/16
to elixir-l...@googlegroups.com
In such cases, I use macros:


Right now it feels this is a very specific use case to justify being added as part of Elixir.



José Valim
Skype: jv.ptec
Founder and Director of R&D

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CABR-7m0R8j52Y2r57-hWomJ-nz%2B0R0Q5Q01B-xm5CAZH0jGHbw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Waldemar Rachwał

unread,
Nov 4, 2016, 9:46:54 AM11/4/16
to elixir-l...@googlegroups.com
Only skimmed Inspect.Algebra... Could those macros give possibilities to achieve what Record.defrecord/3 provides? Among other things: pattern-matching capabilities, "tell me index of the field by name"...

Maybe I should have avoided dwelling on my use case, and formulate more general wish: Shouldn't tuples get functional interface 'a la' existing records, but for tuples in general, not necessarily for tuples being at once 'records'?

Regards,
Waldemar.

Robert Virding

unread,
Nov 7, 2016, 5:26:40 AM11/7/16
to elixir-lang-core
How do you mean a "functional interface". One issue with pattern matching a tuple is that you have to write the whole tuple. There is no way of saying to test if it is a tuple and is the Nth element 42. The (erlang) record interface does this expansion in a pattern, it expands the more functional interface to the right sized tuple where the first element is the record name, the elements in which you are interested to the patterns you give and all the other elements become _ so as to match anything[*]. So a tuple interface must do the same thing, which is why I was asking about the functional interface.

Robert

[*] You can do the "matching" in a guard if you wish but then the macro becomes more complex. The record interface expansion in the body is the basically same except that instead of _ for the other elements there is the default values.


On Friday, 4 November 2016 14:46:54 UTC+1, Waldemar Rachwał wrote:
Only skimmed Inspect.Algebra... Could those macros give possibilities to achieve what Record.defrecord/3 provides? Among other things: pattern-matching capabilities, "tell me index of the field by name"...

Maybe I should have avoided dwelling on my use case, and formulate more general wish: Shouldn't tuples get functional interface 'a la' existing records, but for tuples in general, not necessarily for tuples being at once 'records'?

Regards,
Waldemar.
On Fri, Nov 4, 2016 at 1:21 PM, José Valim <jose....@plataformatec.com.br> wrote:
In such cases, I use macros:


Right now it feels this is a very specific use case to justify being added as part of Elixir.



José Valim
Skype: jv.ptec
Founder and Director of R&D

On Fri, Nov 4, 2016 at 1:19 PM, Waldemar Rachwał <waldemar...@gmail.com> wrote:
Hello,

The rationale behind the proposal is the fact there are cases the records can be inappropriate. They provide excellent interface, but well, sometimes the tag atom at first position (index 0) rather harms than helps.

One such use case I found when dealing with ETS tables.

ETS entries are tuples. While entries are homogenic, one record definition which tuple data looks like {:tag, key, field1, ...} seems to be a good fit and only one has to tell ETS the key is at second position (index 1).

However, when it comes to store many tuples of different shapes in one table, the key itself should differentiate these shapes and the instance within given shape, something like {:tag, key}, and then the alone :tag field of a record becomes quite redundant. In such heterogenic ETS tables, existing records have also their own use: for example to hold singular entries each with "global" counters as fields.

Obviously, this is the real use case I encountered. Perhaps there are others. I have no doubt that generally records, in cases one wants to use tuples via functional interface, will be default practice.

I have code ready because I used the stuff earlier from an auxiliary module. In Elixir the Tuple module and deftuple(p) seem natural, but I was never good at naming things...

What do you think?

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.

Waldemar Rachwał

unread,
Nov 7, 2016, 9:30:12 AM11/7/16
to elixir-l...@googlegroups.com
Hi Robert,

"(...) Shouldn't tuples get functional interface 'a la' existing records, but for tuples in general, not necessarily for tuples being at once 'records'?"

Strictly speaking `Record.defrecord(p)/2,3` macro produces a set of `record/0,1,2` (substitute record with actual name given by user) which are... macros. In use these generated macros look like function calls (even in pattern-match contexts), and that's why I wrote functional. The macros address all problems you listed and offers other goodies, esp. record/1 macro is nicely "overloaded". For example, for given field name (literal atom at compile time) returns zero-based index of that field in a tuple (e.g. name(:user) returns integer at compile time).

The problem with records I encountered is they are *specific* tuples. I need tuples not being records (for a good reason IMO) but with the same API Elixir records do offer.

That's why I proposed `Tuple.deftuple(p)/2` generating `tuple/0,1,2`. The code doing it, as one can suspect, has been stolen from Record module and adopted for general-tuples-not-records.

As the proposal seemed to be rejected, at least for now, I am going to publish the code on github.

Waldemar.

To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/69b83195-e8d6-4866-953c-0c561352715a%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages