Oliver

Oliver

One common problem we face in constructing lists is that there is (AFAIK) no support for conditionally inserting members into list declarations.

You can’t write:

allow_even? = false
[
1,
if allow_even? do 2 end,
3
]

because the result would be [1, nil, 3], though syntactically a lot of code would be easier and more readable for us if you could do that.

What if returning a very specific value, like :ignore_list_member would lead to a list being constructed like this:

[1, :ignore_list_member, 3] ==> [1, 3]

Functions could return specifically this value if there’s nothing to insert.

def foo(x), do: if rem(x, 2) != 0 do x else :ignore_list_member end
[
foo(1),
foo(2),
foo(3)
]
===> [1, 3]

Right now we typically do something like piping a whole list like this:

allow_even? = false
[
1,
if allow_even? do 2 end,
3
]
|> Enum.reject(&is_nil/1)

which is fine, but I wonder if this could be solved more conveniently and generic without the need to walk the list a second time after constructing it - just once when it’s “constructed” with the declarative syntax.

If it’s not possible with small effort, I still thank you for reading this. :slightly_smiling_face:

Showing Posts 1 to 10

LostKobrakai

LostKobrakai

Ages ago I did look into mimicing dart lists, which do have an add item conditionally synta as well as spreading loops onto the list:

linusdm

linusdm

I was thinking about this language feature too. As @LostKobrakai mentioned, this is a core feature in Dart. It’s documented here: Collections.

I came across a very nice podcast, where Robert Nystrom explains how this works in Dart, and why they choose to make it part of the language (tldr; because it’s handy to build collections like this, in a context where you’re building UI’s declaratively).

LV side-steps this problem with class lists by ignoring falsey values in these lists. I’m not sure the pull towards this feature is just as strong in Elixir, as it was in Dart. Afaik this can’t be emulated with macros, or something similar, but must be a core language feature.

I’m curious if there were previous discussions about this feature, and if there was consensus in the past about it.

LostKobrakai

LostKobrakai

After I posted a macro implementing those features :smiley: It cannot be done without extra syntax, though elixir won’t be able to do so either. It only has a but more flexibility around new syntax over macros.

Oliver

Oliver OP

That’s an interesting proposal, but looking at the implementation it requires list concatenation underneath if I understand it right.

That would make it very similar to what we’re currently doing:

[1, 2, 3] ++
some_function_returning_a_list() ++ 
[4, 5]

which could also handle if constructs

[1, 2, 3] ++
if x do [:something] else [] end ++ 
[4, 5]

I was kind of hoping that the declarative syntax could be done in such a way at language level that it can avoid paying for concatenation in that way. (Unless ++ concatenation is very efficient. I always resorted to [ x | xs ] syntax where possible assuming ++ comes at a higher cost.)

linusdm

linusdm

Haha, I see where I messed up. I mean without wrapping the list as a whole :sweat_smile: I was thinking of a solution that doesn’t require a certain context to be set up. Maybe only a marcro inside a list.

linusdm

linusdm

Since this is about list literals, I wouldn’t worry too much about performance.

D4no0

D4no0

What is the problem of using macro proposed by @LostKobrakai ?

I’m not a fan of this becoming a language feature, as it involves a lot of mental overload vs not having to write 2 more lines of code.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

If the value is conditionally there then there is no avoiding paying for concatenation. Lists are linked lists, they’re built from back to front. If part of the back is different depending on a runtime value then you have to pay a runtime cost to deal with it.

gregvaughn

gregvaughn

You can use the filter of a for comprehension

iex(9)> require Integer
Integer
iex(10)> allow_even? = false
false
iex(11)> for x <- 1..3, !Integer.is_even(x) || allow_even?, do: x
[1, 3]
iex(12)> allow_even? = true
true
iex(13)> for x <- 1..3, !Integer.is_even(x) || allow_even?, do: x
[1, 2, 3]

or you could use Enum.flat_map but then you’re creating intermediate lists

iex(14)> Enum.flat_map(1..3, fn
...(14)>   x when not Integer.is_even(x) or allow_even? -> [x]
...(14)>   _ -> []
...(14)> end)
[1, 2, 3]
iex(15)> allow_even? = false
false
iex(16)> Enum.flat_map(1..3, fn
...(16)>   x when not Integer.is_even(x) or allow_even? -> [x]
...(16)>   _ -> []
...(16)> end)
[1, 3]
dimitarvp

dimitarvp

On the very rare occasion I’ve done this I just used a list of lists (where the conditional adding of a thing added a non-empty list, and if the condition was false then it simply added an empty list) and then just do List.flatten at the end.

I understand the appeal of having such a language construct but it’s IMO too niche.

Where Next? Top

Trending in Proposals: Ideas Top

a3kov
I recently learned about this API and was surprised there’s no explicit support for it in the the Phoenix. Example use cases: A webs...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews