如何在不参考Elixir 1.0.3中的模块的情况下引用函数中的模块变量?在其父范围内?

Nat*_*ese 6 import scope module elixir

我想在Elixir 1.0.3中创建一个函数,引用其"父"范围内的变量.在这种情况下,其父作用域是一个模块.

这里的代码与我在上一个问题中使用的代码相同:

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
Run Code Online (Sandbox Code Playgroud)

如果我将其更改为以下内容:

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
Run Code Online (Sandbox Code Playgroud)

它编译得很好,但如果我尝试msgurr函数,我会收到以下错误:

** (UndefinedFunctionError) undefined function: Rec.counter/0
    Rec.counter()
    recursion_and_import_test.exs:5: Rec.msgurr/2
Run Code Online (Sandbox Code Playgroud)

我也尝试过以下方法:

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
Run Code Online (Sandbox Code Playgroud)

我在这里得到一个编译时警告:➜ubuntuelixirc recursiontest.exs recursion_and_import_test.exs:1:警告:重新定义模块Rec recursion_and_import_test.exs:2:警告:变量计数器未使用recursion_and_import_test.exs:4:警告:unused import录音

当我尝试使用msgurr函数时:

➜ubuntuiex 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
Run Code Online (Sandbox Code Playgroud)

我似乎无法将自己的变量从模块导入到该模块内的函数中.

我已经查看了导入文档,但我似乎对如何做这类事情没有多大意义.我应该查看Erlang文档吗?

Fre*_*Dog 4

您将模块与对象混淆了。

Rec.counter 
Run Code Online (Sandbox Code Playgroud)

始终指记录模块内的函数。这就是错误消息告诉您的,他们找不到该函数。模块不能像您想象的那样具有变量。

模块可以具有属性。虽然可以用模块属性来伪造你想要的东西,但如果你想使用 Rec.counter 引用它,你应该只创建一个返回常量的函数。

def counter do
  "done!"
end
Run Code Online (Sandbox Code Playgroud)

这里有更多关于模块属性的内容,但是如果你想能够在 Elixir 中思考,你需要开始思考“函数而不是变量”。

  • 模块变量意味着可变状态,这打破了函数式编程的原则之一。有很多内容超出了我在评论中可以说的内容。您可能会发现此线程很有用 https://groups.google.com/forum/?hl=en#!topic/elixir-lang-talk/jvl9THiFFEI (2认同)
  • 这也是为了避免Python中的“local”之类的事情,在这种情况下,“模块变量”和函数变量之间可能会发生冲突。消除歧义并引入显式符号会更清晰,因为它表明了意图(即您使用 @attribute 因为在某个地方您会需要它)。 (2认同)