# Why does \`elem/2\` exist?

**URL:** <https://forum.elixirforum.com/t/why-does-elem-2-exist/64854>\
**Category:** Questions\
**Tags:** functions\
**Created:** [July 11, 2024, 3:04am UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854 "2024-07-11T03:04:54Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![sodapopcan](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sodapopcan/32/34668_2.png) [@sodapopcan](https://forum.elixirforum.com/u/sodapopcan)\
**Post date:** [July 11, 2024, 3:04am UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/1 "2024-07-11T03:04:54Z")

</div>

I’ve been in the Elixir world for five years—not super long but also not super short. In this time I have seen lots of code that uses `elem/2` but _not once_ have I ever seen a situation where it made code clearer and in fact has always made code _less_ clear. It seems its main use it to “not break pipelines.” To put it lightly: this is a non-goal. I have never run into a situation where pattern matching isn’t way way way _waaaaaaaay_ clearer than `elem/2`, even if it means breaking the pipe.

IMO if we ever see an Elixir 2.0 this function should be removed from the language. But please tell me why `elem/2` is indispensable to your Elixir work! I realize I’m using very dismissive language but I’m genuinely curious if there is a good use-case for it I’ve never thought of.

---

<div class="post-metadata">

**Author:** ![arcanemachine](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/arcanemachine/32/29109_2.png) [@arcanemachine](https://forum.elixirforum.com/u/arcanemachine)\
**Post date:** [July 11, 2024, 3:21am UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/2 "2024-07-11T03:21:41Z")

</div>

Sometimes I just want to write a one-liner or pipeline and I’m too lazy to get fancy with the error handling. 🤷‍♂️

---

<div class="post-metadata">

**Author:** ![dorgan](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dorgan/32/22107_2.png) [@dorgan](https://forum.elixirforum.com/u/dorgan)\
**Post date:** [July 11, 2024, 3:23am UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/3 "2024-07-11T03:23:17Z")

</div>

- You have tuples, a fixed size array of elements.
- You can access them by a random index.
- There is no syntax to access a random index of a tuple
- Pattern matching requires you to know the length of the tuple up-front

I think it makes sense to have such a function be part of the standard library. The reasoning is quite simple: if you provide a builtin data structure, it makes sense to provide an API to read and write to it.

Wether or not it’s idiomatic to access a random element of a tuple is a whole different topic.

---

<div class="post-metadata">

**Author:** ![v0idpwn](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/v0idpwn/32/30493_2.png) [@v0idpwn](https://forum.elixirforum.com/u/v0idpwn)\
**Post date:** [July 11, 2024, 3:43am UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/4 "2024-07-11T03:43:34Z")

</div>

Agree 100% with doorgan.

With regards to elem/2 in pipelines, maybe a credo check for this would be useful.

---

<div class="post-metadata">

**Author:** ![heilong](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/heilong/32/35976_2.png) [@heilong](https://forum.elixirforum.com/u/heilong)\
**Post date:** [July 11, 2024, 6:59am UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/5 "2024-07-11T06:59:03Z")

</div>

`elem/2` can be used in guards, pattern matching cannot

`elem/2` is O(1) access to a vector (the only other O(1) example is binaries).

Pattern matching with large tuples is verbose and it’s easy to get the wrong element (why count wildcard matches when you can write the correct index into a function argument).

In the future, it seems we will get O(1) _update_ of tuples in contexts where the compiler knows there are no shared references. So maybe time to incorporate `:erlang.setelement/3` into Elixir somehow.

---

<div class="post-metadata">

**Author:** ![BartOtten](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartotten/32/25440_2.png) [@BartOtten](https://forum.elixirforum.com/u/BartOtten)\
**Post date:** [July 11, 2024, 7:13am UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/6 "2024-07-11T07:13:12Z")

</div>

> Pattern matching with large tuples is verbose and it’s easy to get the wrong element

If you are on control of the data: Use Records to overcome this issue

---

<div class="post-metadata">

**Author:** ![dimitarvp](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/32/38664_2.png) [@dimitarvp](https://forum.elixirforum.com/u/dimitarvp)\
**Post date:** [July 11, 2024, 9:33am UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/7 "2024-07-11T09:33:53Z")

</div>

> [@sodapopcan](#):
>
> t seems its main use it to “not break pipelines.” To put it lightly: this is a non-goal.

Agreed, but it has to be noted that [`then`](https://hexdocs.pm/elixir/Kernel.html#then/2) – which solves the problem of not breaking pipelines – was only added in Elixir 1.12.

> [@arcanemachine](#):
>
> Sometimes I just want to write a one-liner or pipeline and I’m too lazy to get fancy with the error handling. 🤷‍♂️

Use `then`.

---

<div class="post-metadata">

**Author:** ![sodapopcan](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sodapopcan/32/34668_2.png) [@sodapopcan](https://forum.elixirforum.com/u/sodapopcan)\
**Post date:** [July 11, 2024, 3:09pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/8 "2024-07-11T15:09:06Z")

</div>

Thanks for all the responses?

> [@dorgan](#):
>
> Wether or not it’s idiomatic to access a random element of a tuple is a whole different topic.

Ya, what I’m really asking is: “Does anyone have an example of an exemplary use of `elem/2`?” I’ve never been in a situation where I don’t know the size of a tuple. I always think of the size as being part of the type as it in other functional languages. But thanks for the thoughtful answer, all that does make sense!

> [@heilong](#):
>
> `elem/2` can be used in guards, pattern matching cannot

I actually wasn’t aware you could use `elem` in guards! I still think pattern matching is clearer.

> [@heilong](#):
>
> Pattern matching with large tuples

The question here is why do you have large tuples? I don’t think I’ve come across one with more than 4 before, though I could be wrong. The type of work I do is very limited to business web apps, but large tuples seem like a massive anti-pattern to me.

> [@heilong](#):
>
> In the future, it seems we will get O(1) _update_ of tuples in contexts where the compiler knows there are no shared references. So maybe time to incorporate `:erlang.setelement/3` into Elixir somehow.

I’m having trouble finding it but I remember the docs recommending against `put_elem` and to pattern match and create a new tuple instead. Though maybe it’s gone and no longer the advice anymore? Or I’m just not looking hard enough.

> [@BartOtten](#):
>
> If you are on control of the data: Use Records to overcome this issue

This interesting as I’m aware of but never used records before.

---

<div class="post-metadata">

**Author:** ![cevado](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/cevado/32/40655_2.png) [@cevado](https://forum.elixirforum.com/u/cevado)\
**Post date:** [July 11, 2024, 3:23pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/9 "2024-07-11T15:23:01Z")

</div>

> [@BartOtten](#):
>
> If you are on control of the data: Use Records to overcome this issue

I particularly wouldn’t use records in elixir, I think the semantics are not particularly well ported. the only use I see for records in elixir is to interact with erlang existing records. I was even thinking to open an issue/suggest changes on that in the mailing list but didn’t had time… in this topic I showed a gist of it:  
[https://forum.elixirforum.com/t/any-reason-for-the-different-semantics-with-records-in-elixir/](https://forum.elixirforum.com/t/any-reason-for-the-different-semantics-with-records-in-elixir/)

but I guess i’m going too off-topic here 😄

---

<div class="post-metadata">

**Author:** ![sodapopcan](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sodapopcan/32/34668_2.png) [@sodapopcan](https://forum.elixirforum.com/u/sodapopcan)\
**Post date:** [July 11, 2024, 3:24pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/10 "2024-07-11T15:24:43Z")

</div>

> [@v0idpwn](#):
>
> With regards to elem/2 in pipelines, maybe a credo check for this would be useful.

I don’t actually have a problem with it in any apps I work on, even at work, was just generally looking for a case where pattern matching isn’t better. Though it could actually be a fun but jarring addition to [recode](https://github.com/hrzndhrn/recode) 😅

---

<div class="post-metadata">

**Author:** ![sodapopcan](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sodapopcan/32/34668_2.png) [@sodapopcan](https://forum.elixirforum.com/u/sodapopcan)\
**Post date:** [July 11, 2024, 3:25pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/11 "2024-07-11T15:25:40Z")

</div>

> [@cevado](#):
>
> but I guess i’m going too off-topic here 😄

Everyone is always free to go off topic in any thread I create 😅

---

<div class="post-metadata">

**Author:** ![LostKobrakai](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/lostkobrakai/32/3072_2.png) [@LostKobrakai](https://forum.elixirforum.com/u/LostKobrakai)\
**Post date:** [July 11, 2024, 3:30pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/12 "2024-07-11T15:30:43Z")

</div>

> [@sodapopcan](#):
>
> It seems its main use it to “not break pipelines.” To put it lightly: this is a non-goal.

It’s main use is accessing a tuple value using an index, which works no matter the size of tuple and in context, where pattern matching is not an option. Just like there’s `:erlang.map_get` for maps, because pattern matching is not enough.

> [@sodapopcan](#):
>
> Ya, what I’m really asking is: “Does anyone have an example of an exemplary use of `elem/2`?”

There’s places in OTP, where you might get differently sized tuples, where leading parts of them contain the same data. You can use `elem/2` to select the common fields without needing to know which specific tuple you got if the differenciation doesn’t matter for the code. It also means your code doesn’t break if OTP decides to add another version of tuple with yet another additional datapoint added to the end.

> If flag `timestamp`, `strict_monotonic_timestamp`, or `monotonic_timestamp` is specified, the first tuple element is `trace_ts` instead, and the time stamp is added as an extra element last in the message tuple.

> **[Session - trace — OTP 29.0.2 (kernel 11.0.2)](https://www.erlang.org/doc/apps/kernel/trace.html#process/4)**
>
> Equivalent to erlang:trace\_delivered(Tracee) except that it is run within the given session/0.

Usually one would likely use maps for such a usecase, but sticking to tuples for performance sensitive calls like around tracing is also a good idea.

Also e.g. elixir’s record handling code wouldn’t be a lot more complex macro magic without having such functionality. Technically it doesn’t use `Kernel.elem/2`, but it optimizes by calling `:erlang.element/2` directly, which is also what `Kernel.elem/2` is using.

---

<div class="post-metadata">

**Author:** ![dimitarvp](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/32/38664_2.png) [@dimitarvp](https://forum.elixirforum.com/u/dimitarvp)\
**Post date:** [July 11, 2024, 3:35pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/13 "2024-07-11T15:35:25Z")

</div>

> [@LostKobrakai](#):
>
> Usually one would likely use maps for such a usecase, but sticking to tuples for performance sensitive calls like around tracing is also a good idea.

Agreed about performance. I see nothing that does not allow for multi-headed `case` however. I still don’t see the value of `elem/2` in these cases. 🤔

---

<div class="post-metadata">

**Author:** ![cevado](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/cevado/32/40655_2.png) [@cevado](https://forum.elixirforum.com/u/cevado)\
**Post date:** [July 11, 2024, 3:40pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/14 "2024-07-11T15:40:38Z")

</div>

> [@sodapopcan](#):
>
> IMO if we ever see an Elixir 2.0 this function should be removed from the language. But please tell me why `elem/2` is indispensable to your Elixir work! I realize I’m using very dismissive language but I’m genuinely curious if there is a good use-case for it I’ve never thought of.

I belive it’s not a question of how often it’s used but of having handy and easy way of random access to a tuple in elixir. Also that elixir changes the indexing of tuples/list in erlang, erlang indexes starts at 1, elixir ones starts at 0… so having the counterpart of the `element/2` erlang function in elixir that follows the index pattern that elixir establishes is needed IMO.

---

<div class="post-metadata">

**Author:** ![al2o3cr](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/al2o3cr/32/3457_2.png) [@al2o3cr](https://forum.elixirforum.com/u/al2o3cr)\
**Post date:** [July 11, 2024, 3:40pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/15 "2024-07-11T15:40:46Z")

</div>

Short short version: `elem/2` exists because typing `:erlang.element` is too many characters.

> [@BartOtten](#):
>
> If you are on control of the data: Use Records to overcome this issue

`Record` also provides some examples of places where `elem` (or it’s Erlang equivalent) are useful, for instance `is_record?`:

[https://github.com/elixir-lang/elixir/blob/47abe2d107e654ccede845356773bcf6e11ef7cb/lib/elixir/lib/record.ex#L136-L138](https://github.com/elixir-lang/elixir/blob/47abe2d107e654ccede845356773bcf6e11ef7cb/lib/elixir/lib/record.ex#L136-L138)

* * *

> [@heilong](#):
>
> In the future, it seems we will get O(1) _update_ of tuples in contexts where the compiler knows there are no shared references. So maybe time to incorporate `:erlang.setelement/3` into Elixir somehow.

My interpretation of the release notes about `setelement` optimizations is that sequences like this one (also from `Record`) may get a boost from the compiler and/or JIT:

[https://github.com/elixir-lang/elixir/blob/47abe2d107e654ccede845356773bcf6e11ef7cb/lib/elixir/lib/record.ex#L472-L478](https://github.com/elixir-lang/elixir/blob/47abe2d107e654ccede845356773bcf6e11ef7cb/lib/elixir/lib/record.ex#L472-L478)

Since the intermediate tuples don’t escape the function, the `reduce` could do all the mutation in-place.

---

<div class="post-metadata">

**Author:** ![zachallaun](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/zachallaun/32/29208_2.png) [@zachallaun](https://forum.elixirforum.com/u/zachallaun)\
**Post date:** [July 11, 2024, 3:59pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/16 "2024-07-11T15:59:39Z")

</div>

> [@sodapopcan](#):
>
> The question here is why do you have large tuples? I don’t think I’ve come across one with more than 4 before, though I could be wrong. The type of work I do is very limited to business web apps, but large tuples seem like a massive anti-pattern to me.

An example from a project I contribute to: [`Lexical.Document.Lines`](https://github.com/lexical-lsp/lexical/blob/34ee0716681eb346bffba67ce77febc047189b61/projects/lexical_shared/lib/lexical/document/lines.ex)

The key insight is that a tuple provides O(1) access to any of its elements, whereas a list is O(n). So if you need a data structure that provides fast access to any arbitrary line of a document, you reach for a tuple. (And then you use `elem/2` for access, since you don’t know what its length will be.)

---

<div class="post-metadata">

**Author:** ![dimitarvp](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/32/38664_2.png) [@dimitarvp](https://forum.elixirforum.com/u/dimitarvp)\
**Post date:** [July 11, 2024, 4:10pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/17 "2024-07-11T16:10:25Z")

</div>

> [@zachallaun](#):
>
> you reach for a tuple. (And then you use `elem/2` for access, since you don’t know what its length will be.)

I still don’t get this, how could you _not_ know? I mean there are several variants, right? It’s not like these variants are 1000+. What’s the problem with multi-headed `case`?

---

<div class="post-metadata">

**Author:** ![zachallaun](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/zachallaun/32/29208_2.png) [@zachallaun](https://forum.elixirforum.com/u/zachallaun)\
**Post date:** [July 11, 2024, 4:20pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/18 "2024-07-11T16:20:11Z")

</div>

> [@dimitarvp](#):
>
> I still don’t get this, how could you _not_ know? I mean there are several variants, right? It’s not like these variants are 1000+. What’s the problem with multi-headed `case`?

[See here](https://github.com/lexical-lsp/lexical/blob/34ee0716681eb346bffba67ce77febc047189b61/projects/lexical_shared/lib/lexical/document/lines.ex#L22-L25); the tuple size is however many lines the document is long. So a file with 100 lines will have a 100-element tuple. A file with 2000 lines will have a 2000-element tuple.

---

<div class="post-metadata">

**Author:** ![dimitarvp](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/32/38664_2.png) [@dimitarvp](https://forum.elixirforum.com/u/dimitarvp)\
**Post date:** [July 11, 2024, 4:41pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/19 "2024-07-11T16:41:12Z")

</div>

Aha, I see, reading files (and the like) into memory.

I was thinking about how e.g. Floki does stuff where you always get a recursive tri-tuple.

---

<div class="post-metadata">

**Author:** ![sodapopcan](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sodapopcan/32/34668_2.png) [@sodapopcan](https://forum.elixirforum.com/u/sodapopcan)\
**Post date:** [July 11, 2024, 5:49pm UTC](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854/20 "2024-07-11T17:49:06Z")

</div>

Thanks Zach! A real world example-usage of large tuples of unknown size is exactly what I was looking for, I just didn’t ask the question very well …and I may or may not have been a little tipsy when I opened the topic 😬 I couldn’t for the life of me think of an example for myself. I guess `elem/2` can stay 😉

And hey, I use that project you contribute to!

[Next page](https://forum.elixirforum.com/t/why-does-elem-2-exist/64854.md?page=2)
