Oliver
Allowing an ignored member in list construction?
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. ![]()
Most Liked
benwilson512
Yes, but this happens rather a lot and is very well optimized. Eg an Enum.map is a 2x walk because you have to build up the result backwards and then reverse it (or use a body recursive stack, but that’s still functionally a 2x walk since you have to pop the stack).
If you have literally just one optional item btw you can:
if optional_thing do
[a, optional_thing, b]
else
[a, b]
end
If you are trying to construct a list that has many different items that may optional interspersed amongst items that are not, I don’t see how the compiler is supposed to do constant optimization. Definitionally you aren’t constructing a constant, you’re constructing a value who’s length varies by a bunch of different values.
Overall I think this discussion of costs is probably misplaced. Are we talking about lists that are literally a handful of items long? If so we’re in hyper optimization land and the code that performs best will rely heavily on exactly what you’re trying to do.
al2o3cr
At a minimum, I think this would need some alternative syntax because this is already valid Elixir:
[
:foo,
if x.something? do :bar end,
:baz
]
This is distinctly different from Dart, where the regular if is a statement with no value so putting it inside an expression would otherwise be meaningless.
That syntax would also cause headaches for referential transparency, since this should be “the same” code as the above:
extra_var = if x.something? do :bar end
[
:foo,
extra_var,
:baz
]
IMO the better approach is to use a domain-appropriate “empty” element and clean it up if needed. Cleanup may not even be strictly necessary - for instance, if you’re producing a big iolist value with optional parts then [] is a perfectly fine “skip this and go to the next element” marker.
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.
Popular in Proposals: Ideas
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









