Эликсир не может создать структуру в том же файле, где он определен - PullRequest
0 голосов
/ 26 мая 2018

Я собираюсь предвосхитить это, сказав, что я новичок в мире Эликсира (и вообще функционального программирования).В настоящее время я изучаю типы словарей и наткнулся на структуры.Я определил этот, согласно инструкции моей книги:

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

После этого книга работает в iex до конца главы, но я хотел, чтобы моя была в файле.Я попытался создать экземпляр этой структуры (со всеми значениями, установленными по умолчанию), например так:

sub = %Subscriber{}

Эта игра вызывает ошибку CompileError:

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 голосов
/ 24 октября 2018

Что я узнал о [вашей конкретной ошибке компиляции] о невозможности использовать структуру в том же файле, в котором она определена, это, как правило, означает, что вы обращаетесь к структуре или используете ее из лексической области видимости внешнего файла.

Просто создайте свой экземпляр структуры в функции другого модуля, а не во внешней области файла («контекст»), а затем вызовите эту функцию, чтобы запустить его.

Это мой простой пример использования структуры с именем 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
0 голосов
/ 26 мая 2018

кто-то может объяснить, что я здесь делаю неправильно?

Я полагаю, 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 выше должна быть расширена, и до тех пор, пока определение структуры не станет доступным для компилятора, оно не может быть.

...