Elixir无法在定义它的同一文件中创建结构



首先,我要说我是Elixir世界(以及一般的函数式编程(的新手。我目前正在学习字典类型,并遇到了结构。我根据我的书中的说明定义了这个:

defmodule Subscriber do
defstruct name: "", paid: false, over_18: true
end

在那之后,这本书在本章的其余部分都在 iex 中工作,但我想把我的放在一个文件中。我尝试创建此结构的实例(所有值都设置为默认值(,如下所示:

sub = %Subscriber{}

这游戏我是一个编译错误:

CompileError: cannot access struct Subscriber, the struct was not yet defined or the struct is being accessed in the same context that defines it

它在 iex 中工作正常,但就像我说的,我宁愿把它放在文件中。有人可以解释我在这里做错了什么吗?

有人可以解释我在这里做错了什么吗?

我相信,iex已经解释了问题所在,我会毫不犹豫地重复一遍:">结构是在定义它的同一上下文中访问的"。

它在IEX中工作正常

是的,因为iex是一个 REPL,它会编译每个语句

。Elixir是一种编译语言。一般情况下的编译单元是一个文件。在 REPL 中,它是一个完整的语句。除非代码被编译,否则无法直接访问它(但延迟调用仍然可用(。

这将起作用:

defmodule A, do: defstruct foo: :bar
defmodule B, do: def b, do: IO.inspect %A{}
B.b

这也将起作用:

defmodule A, do: defstruct foo: :bar
IO.inspect struct(A)

但是显式调用%A要求编译器知道如何处理以下 AST(请参阅第 2 行(:

quote do: %A{}                      
#⇒ {:%, [], 
#    [{:__aliases__, [alias: false], [:A]},
#    {:%{}, [], []}]}

虽然A只是一个原子(是的,它是一个普通的原子,(

is_atom(A)
#⇒ true

它可以很容易地注入到任何 AST 并成功编译。必须展开上述 AST 的第二行,在结构定义可供编译器使用之前,它不能展开。

我了解到[您的特定编译错误]无法在定义的同一文件中使用结构,这通常意味着您正在从外部文件的词法范围访问或使用结构。

只需在另一个模块的函数中创建结构实例,而不是在外部文件范围("context"(中创建结构实例,然后调用该函数使其运行。

这是我在这个文件中使用名为Product的结构的简单示例:

defmodule Product do                     
defstruct [:name, :sku, :upc ]
end
defmodule Main do
def hello do
hh = %Product{name: 'dog'}
IO.puts "Hello, #{hh.name}"
end
end
Main.hello

最新更新