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

时间:2018-05-25 23:47:01

标签: 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中工作正常,但就像我说的,我宁愿把它放在一个文件中。有人可以解释我在这里做错了吗?

2 个答案:

答案 0 :(得分:3)

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

我相信,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的第二行,直到编译器可以使用struct定义,它不能。

答案 1 :(得分:0)

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

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

这是我在单个文件中使用名为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