I could not understand `Enum.each/2` behavior

I found this weird behavior of Enum.each/2
when I use Enum.each/2 within the function, the repo_all/2 returns the same value 3 times but it is supposed to return different values
when I use Enum.each/2 directly the repo_all/2 returning different values

Background: I was creating a helper function to reduce code(Enum.each/2) repetition

defmodule Helper do
  def generate_seed_data(str, opts) do
    Enum.each(0..2, fn _x ->
      repo_all(str, opts)
    end)
  end

  def repo_all(str, opts) do
    IO.puts("#{str}, #{opts}")
  end
end

Helper.generate_seed_data(Faker.Person.name(), Faker.Person.name())
Enum.each(0..2, fn _x -> 
  Helper.repo_all(Faker.Person.name(), Faker.Person.name())
end)

Hi @ambareesha7.

As a quick note, please always post code as text not screen shots. I’m going to have to re-type what you wrote to provide suggestions, and this takes up a lot of extra time.

As far as solving your question goes, this will make more sense if you step through how your program executes.

You have:

Helper.generate_seed_data(Faker.Person.name(), Faker.Person.name())

This is equivalent to:

name1 = Faker.Person.name()
name2 = Faker.Person.name()

Helper.generate_seed_data(name1, name2)

What you’re doing is calling Faker.Person.name(). It returns a string, so name1 has a single string value, and name2 has a single string value at that moment. Then you pass those two concrete strings to your helper and ultimately Enum.each.

In your second situation where you do:

Enum.each(0..2, fn _ ->
  Helper.repo_all(Faker.Person.name(), Faker.Person.name())
end)

The Faker.Person.name() is called inside the Enum.each, which means it’s called multiple times and returns a different value each time.

5 Likes

In generate_seed_data, the str variable is bound outside the fn block in each, so all repetitions refer to the same value.

In the second case you generate a new name on every iteration (because Faker.Person.name() is not pure, it is random).

By the way, each returns :ok in all situations (bar exceptions/throws/non-local returns).

https://www.erlang.org/doc/man/lists.html#foreach-2

2 Likes

Sorry for the screenshot, I edited the post and added text form also,

thank you for the explanation

1 Like