0

I'm new to Elixir. Currently using a Pheonix framework. I need to convert structs to list so I can use them in the select field.

In my user_controller.ex I attempt to convert a struct to list, but the variable user_types_name is always empty.

user_type_names = []
for user <- Accounts.list_user_types() do
     user_type_names ++ [user.name]
end

While in form.html.eex. For additional information

<%= inputs_for f, :user_type, fn cf -> %>
    <%= label cf, :user_type %>
    <%= select cf, :user_type, @user_type_names %>
    <%= error_tag cf, :user_type %>
<% end %>

3 Answers 3

2

All data in Elixir is immutable. ++ is a concatenation operator, not a way to mutate a list by pushing an item onto it.

You'll need to use something like this:

user_type_names = Accounts.list_user_types()
  |> Enum.map(fn(user) -> user.name end)

Or, more concisely:

user_type_names = Accounts.list_user_types()
  |> Enum.map(&(&1.name))
Sign up to request clarification or add additional context in comments.

2 Comments

I used your first suggestion and it worked, thanks. But I'm a bit lost when you used Enum.map(&(&1.name)), can you elaborate it to me?
1

You should perhaps look at Enum.map

Enum.map(1..3, fn x -> x * 2 end)
[2, 4, 6]

Enum.map returns a list by itself, so you might want do something like

user_type_names = Enum.map(Accounts.list_user_types()...)

and this should return a list.

Documentation is pretty well written : https://hexdocs.pm/elixir/Enum.html

Elixir forces you to think about what module ( Enum ) and what function ( map ) you are going to use. Think functional is the key to make things work

Comments

1

In Elixir, for is a construct for comprehensions. Meaning that the result will be a list built with the result of the do clause for each element in the enumerables you use.

So, in your example, you are in fact building a list where each element is the concatenation of user_type_names (which every time is the empty list you assigned) with the current user.name.

What was suggested about assigning won't really work inside the for's do clause, because of the scoping rules. You will be reassigning it but the result will actually be the same, because it will still be the result of the match (=).

The solution is actually far simpler than what you're doing. It's enough to do:

user_type_names = for user <- Accounts.list_user_types(), do: user.name

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.