Making a comprehension level "variable" available to use in another function

I am brand new so sorry if this is obvious but reading through the documentation I’m not able to figure it out. I have a function that returns a list of urls and I want to pattern match that list to a name to be stored in memory then use that name to reference the list in another function but have been unsuccessful so far. Here is the code urls_list is the “variable” name (I know that variable assignment doesn’t exist in elixir I just can’t figure out the right way):

def build_urls() do
      page_num = ["1","2","3","4","5"]
      tail_url = ["/?filter=#link"]
      for page <- page_num, tail <- tail_url do
        urls_list = @endpoint <> page <> tail
      end
    end
  
    def get_body() do
      urls_list
      |> Enum.map(fn url -> handle_response(url) end)
      |> Floki.parse
      |> Floki.find(".review-entry")
      |> Enum.map(fn entry ->
        [{"div", _, [date]}] = Floki.find(entry, "div.italic")
        [{"p", _, [content]}]  = Floki.find(entry, "p.review-content")
        {date, content} 
      end)
    end

You can assign the result of a comprehension to a variable:

urls_list = for page <- page_num, tail <- tail_url do
  @endpoint <> page <> tail
end

Thank you! So to make sure I understand; would it make most sense to just forgo creating the build_urls() function all together and just place it inside the get_body() function?

You can put it in a function if you want, in which case using it would look like:

def build_urls() do
  page_num = ["1","2","3","4","5"]
  tail_url = ["/?filter=#link"]
  for page <- page_num, tail <- tail_url do
    @endpoint <> page <> tail
  end
end

def get_body() do
  build_urls()
  |> Enum.map(fn url -> handle_response(url) end)
  # etc...
end

Values always need to be called from one function or passed in as an argument. You can’t assign a variable in one function and then access in another without passing it in as an argument.

1 Like

Assigning urls_list inside a comprehension is extremely misleading :slight_smile:

Thanks for this warning Aleksei!

Elixir compiler would produce the same warning as well. What happens there, the result of the last expression gets implicitly returned from the function.

def build_urls() do
  page_num = ["1","2","3","4","5"]
  tail_url = ["/?filter=#link"]
  for page <- page_num, tail <- tail_url do
    # urls_list = @endpoint <> page <> tail
    @endpoint <> page <> tail
  end
end

And the result of the comprehension gets returned. The assignment is redundant, I believe it happened to appear in the great answer above due to copy-paste issues.

1 Like

Yup that’s my bad, I had accidentally included it from the original when I copied / pasted. Good catch!

2 Likes