# I am not able to add another element to a list

Hello, I am trying to add another element to a list and for some reason it is giving me errors. I am new to elixir and I have just started, please help me figure this out.
Code:

``````def forloop(list, y) do
if y > 0 do
list = Enum.map list, fn(x) ->
x - 1
if (x == 0) do
x + 6
list = list ++ [9]
end
end

forloop(list, y - 1)
end
end
``````

The error is saying variable list is not used.

Inside `Enum.map` you cannot change the full list (`list = list ++ [9]`) - you can only change the current item (`x`).

So what is a better way of adding an element if x is equal to 0?

If you need to change the full list for each item, then you must look into an `Enum.reduce` based solution.

How will that help? After 1 loops if the starting list was [1, 2, 4], I want the new value to be [6, 1, 3, 8] and after another loop it would be [5, 6, 2, 7, 8].

Enum.reduce takes a function like Enum.map but the function has two arguments, the current item, and the accumulator. So you could use the list as the accumulator.

But that wouldnâ€™t map it unto list like map would.

Plot twist: Enum.map is syntactic sugar for Enum.reduce

Well when I try to do:

``````list = Enum.reduce list, list, fn(x, acc) ->
x - 1
if (x == 0) do
x + 6
acc ++ [9]
end
end
``````

it gives me an error

Values in elixir are not mutable. Youâ€™re doing a lot of things and then just throwing the answer away.

``````list = Enum.reduce list, list, fn(x, acc) ->
x - 1   # result gets thrown away
if (x == 0) do
x + 6  # result gets thrown away
acc ++ [9]
end  # result is nil if (x != 0)
end
``````
1 Like

Ok, so from what I understood I made the code this:

``````list = Enum.map list, fn(x) ->
x = x - 1
if (x == 0) do
x + 6
else
x
end
end
``````

This doesnâ€™t help me with adding a new element to the list but it works for x. Can you help me make it add a new element? I tried this and it didnâ€™t work:

``````list = Enum.reduce list, list, fn(x, acc) ->
x = x - 1
if (x == 0) do
x + 6
acc ++ [9]
else
x
end
end
``````

When you reduce, you are building the list back up from scratch. This allows you to both update the existing items, and add new items. The result of your anonymous function should always be the new, updated acc. Try:

``````list =
Enum.reduce(list, [], fn item, acc ->
case item - 1 do
0 ->
[6, 9 | acc]
x ->
[x | acc]
end
end)
``````
2 Likes

``````defmodule IAmCool do
def forloop(list0, y) do
if y > 0 do
list1 =
Enum.map(list0, fn x0 ->
x0 - 1

if x0 == 0 do
x0 + 6
list2 = list0 ++ [9]
end
end)

forloop(list1, y - 1)
end
end
end
``````

warning: variable â€ślist2â€ť is unused (if the variable is not meant to be used, prefix it with an underscore)
#cell:10: IAmCool.forloop/2

Also `x + 6` does does nothing if you donâ€™t assign it to a variable. also due to lexical scope the variables assignment do not escape the if block.

1 Like

maybe more descriptive variable names will help

``````starting_list = []
new_list =
Enum.reduce(source_list, starting_list, fn source_item, list_so_far ->
case source_item - 1 do
0 ->
[6, 9 | list_so_far]
other_number ->
[other_number | list_so_far]
end
end)
``````
2 Likes

Please if you donâ€™t mind, can you translate it to an if statement instead of case statement. It works fine but I want to better understand this solution.

``````case source_item - 1 do
0 ->
[6, 9 | list_so_far]
other_number ->
[other_number | list_so_far]
end
``````

is equivalent to

``````if source_item - 1 == 0 do
[6, 9 | list_so_far]
else
[source_item - 1 | list_so_far]
end
``````

As you can see, it removes the need to do `source_item - 1` twice, because it binds the result to `other_number` (in those cases where it is not 0)

2 Likes
``````defmodule IAmCool do
# First thing, SnakeCase is used for Modules, undercore is use for function names and variables.
# Secondly, use pattern matching to avoid ives (if)
def for_loop(list0, y) when y > 0 do
list1 =
Enum.map(list0, fn x0 ->
# Assign the result of x+1 to a variable
x1 = x0 - 1

# read inside the if block to know why I do this.
{list3, x3} =
if x1 == 0 do
# Assign the result of x+6 to a variable
x2 = x1 + 6

# here you want to modify the value of an outter variable (list0) so
# doing: list0 = list0 ++ [9]
# will not work as variables do not leak out if blocks in Elixir.
# so we just return and assign the result to variables via pattern matching
list2 = list0 ++ [9]

{list2, x2}
end

# alight, now we return list0
# and the question is. What do you need x3 for?
list3
end)

for_loop(list1, y - 1)
end

def for_loop(_list0, _y),
do: nil
end
``````

Pattern matching can be used to avoid the case/if/etc conditional.

``````starting_list = []
new_list =
Enum.reduce(source_list, starting_list, fn
source_item, list_so_far when source_item - 1 == 0  ->
[6, 9 | list_so_far]

source_item, list_so_far ->
[source_item - 1 | list_so_far]
end
end)
``````

and even more simplified

``````starting_list = []
new_list =
Enum.reduce(source_list, starting_list, fn
1, list_so_far  ->
[6, 9 | list_so_far]

source_item, list_so_far ->
[source_item - 1 | list_so_far]
end
end)
``````

NOTE: remember to Enum.reverse() your list after Enum.reduce()

1 Like