如何导入另一个文件中定义的自定义模块?

时间:2018-08-02 23:28:24

标签: elixir

a.exs:

defmodule A do
  def greet, do: IO.puts "hello"
end

b.exs:

defmodule B do
  import A
  def say_hello, do: greet
end

结果:

~/elixir_programs$ iex b.exs
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]

** (CompileError) b.exs:2: module A is not loaded and could not be found

~/elixir_programs$ tree .
.
├── a.exs
├── app1.exs
├── b.exs
....

为此,您如何使用限定名称来调用另一个模块中定义的函数:

b.exs:

defmodule B do
  def say_hello, do: A.greet
end

~/elixir_programs$ iex b.exs
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)> B.say_hello
** (UndefinedFunctionError) function A.greet/0 is undefined (module A is not available)
    A.greet()

好的,这可行:

iex(1)> c "a.exs"
[A]

iex(2)> B.say_hello
hello
:ok

4 个答案:

答案 0 :(得分:6)

关于Elixir,有两点需要理解:它是一种编译的语言,它区分编译文件脚本(后者也可以编译,但默认情况下mix不会自动编译。)

与脚本语言(ruby,python,javascript,...)不同,编译语言应该在功能可用之前经过两个阶段:应编译文件,然后然后运行时(阅读:Erlang VM)。一个人不能像我们在ruby中那样require 'foo',或者像在python中那样import bar,并期望它能工作。

Elixir在Code模块中提供了方便的助手来在运行时进行编译,包括但不限于:Code.require_file/2Code.compile_file/2

使用mix时,默认情况下仅编译扩展名为.ex non-script 文件。这就是为什么测试文件(即脚本(.exs)永远不会与运行时混淆的原因。

也就是说,有四个主要选项可以使其起作用:

  1. 使用mix项目和名为a.exb.ex的文件。这样一来,您就可以通过运行iex -S mix来获取,编译所有内容。
  2. 使用Code.require_file("a.exs")中的b.exs明确要求a.exs
  3. 通过运行iex告诉iex -r a.exs -r b.exs进行编译(如果需要)并加载所有文件。
  4. 像回答中一样手动进行编译。

答案 1 :(得分:1)

如果所有.exs文件都在同一目录中,则可以运行iex -r *.exs,这会将所有.exs加载到您的iex会话中。您也可以通过iex -r a.exs -r b.exs

一次加载文件

答案 2 :(得分:0)

这有效:

Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> c "a.exs"
[A]

iex(2)> c "b.exs"
[B]

iex(3)> B.say_hello
hello
:ok

iex(4)> 

答案 3 :(得分:0)

您可以在终端中使用 elixrc(确保两个文件都在同一个文件夹中),如下所示:

elixirc a.exs b.exs

这将生成 .beam 文件。这些是 erlang VM 将运行的字节码文件。