Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I refer to a module variable in a function without referring to its module in Elixir 1.0.3? In its parent scope?

I'd like to make a function in Elixir 1.0.3 refer to a variable inside its "parent" scope. In this case, its parent scope is a module.

Here's the same code as that which I used in my last question:

defmodule Rec do
  def msgurr(text, n) when n <= 1 do
    IO.puts text
  end

  def msgurr(text, n) do
    IO.puts text
    msgurr(text, n - 1)
  end
end

If I change it to the following:

defmodule Rec do
  counter = "done!"
  def msgurr(text, n) when n <= 1 do
    IO.puts text
    IO.puts Rec.counter
  end

  def msgurr(text, n) do
    IO.puts text
    msgurr(text, n - 1)
  end
end

It compiles just fine, but I get the following error if I try the msgurr function:

** (UndefinedFunctionError) undefined function: Rec.counter/0
    Rec.counter()
    recursion_and_import_test.exs:5: Rec.msgurr/2

I also tried the following:

defmodule Rec do
  counter = "done!"
  def msgurr(text, n) when n <= 1 do
    import Rec
    IO.puts text
    IO.puts Rec.counter
  end

  def msgurr(text, n) do
    IO.puts text
    msgurr(text, n - 1)
  end
end

I get a compile-time warnings here, though: ➜ ubuntu elixirc recursiontest.exs recursion_and_import_test.exs:1: warning: redefining module Rec recursion_and_import_test.exs:2: warning: variable counter is unused recursion_and_import_test.exs:4: warning: unused import Rec

When I attempt to use the msgurr function:

➜ ubuntu iex Erlang/OTP 17 [erts-6.3] [source] [64-bit] [smp:8:8] [async-threads:10] [kernel-poll:false]

Interactive Elixir (1.0.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> import Rec
nil
iex(2)> Rec.msgurr("blah", 3)
blah
blah
blah
** (UndefinedFunctionError) undefined function: Rec.counter/0
    Rec.counter()
    recursiontest.exs:6: Rec.msgurr/2

I seem to be unable to import a variable of my own from a module into a function inside that module.

I've gone over the import documentation, but I can't seem to make much sense from it of how to do this sort of thing. Should I check the Erlang docs?

like image 563
Nathan Basanese Avatar asked Mar 03 '15 20:03

Nathan Basanese


1 Answers

You are confusing Modules with Objects.

Rec.counter 

Always refers to the function inside the Rec Module. That's what the error messages are telling you, they can't find the function. Modules can't have variables in the way you are thinking of them.

Modules can have attributes. While it might be possible to fudge want you want with a module attribute, you should just make a function that returns a constant if you want to reference it using Rec.counter.

def counter do
  "done!"
end

There's more on module attributes here, but if you want to be able to think in elixir, you need to start thinking "functions not variables".

like image 72
Fred the Magic Wonder Dog Avatar answered Oct 09 '22 00:10

Fred the Magic Wonder Dog