>
> I believe the following code examples are all identically equivalent.
>

Well, the compiler is explicitly telling you that they are not. :)

There are two concepts to understand in the examples you posted: one of
aliasing and the other one is about compile time expansion. In particular,
remember that structs are expanded at compilation time.


> Version 1:
> defmodule Demo do
>     defmodule Demo.Embed do
>         defstruct local: 0
>     end
>
>     defstruct name: "", embed: %Embed{}
> end
>

In this example, you are actually defining a struct named Demo.Demo.Embed.
In this case, when you try to expand %Embed{}, it doesn't see an Embed
alias and then it tries to expand the "root" Embed which does not exist.
That's *not* the error message you reported though. So I am assuming you
mixed something up either when copying the code or the error message.

If we fix the code:

defmodule Demo do
>     defmodule Embed do
>         defstruct local: 0
>     end
>
>     defstruct name: "", embed: %Embed{}
> end
>

Then the error is the one you reported:

== Compilation error on file lib/demo.ex ==
> ** (CompileError) lib/demo.ex:7: cannot access struct Demo.Embed, the
> struct was not yet defined or the struct is being accessed in the same
> context that defines it
>     (elixir) src/elixir_map.erl:58: :elixir_map.translate_struct/4
>     (stdlib) lists.erl:1353: :lists.mapfoldl/3
>     (stdlib) lists.erl:1354: :lists.mapfoldl/3
>

And then:

This: "the struct is being accessed in the same context that defines
> it" is a pretty big hint but I disagree with it. By time line 7 is
> being compiled the Embed struct is already fully defined.
>

The compiler is correct, regardless of how much you disagree with it. :)
Remember that structs are expanded at compile time so when you try to
expand %Embed{}, the defmodule macro was also expanded but the module
contents was not yet executed/defined.

You can effectively think of your code as running twice: one goes through
all the source, doing all the compiler time work, then when you execute it
does another pass, running all of the expanded code.

Version 2 will fail since you can't use a struct before you defined it. The
next two examples are correct.

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4JF6BK1MkZ_bOUuXH33ranJrWnJGo6KV9wLwPKy%2BTcfTQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to