Nesting defmodule inside another defmodule prepends the outer module. So in the first example you actually defined Demo.Demo.Embed, and that's why it couldn't find Demo.Embed.
--
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 elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CACo3ShgwQ5V1bkRQ7_C4A5Kc7y2OGONE%2Bs6wVh7no1rhwzDn3A%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
I believe the following code examples are all identically equivalent.
Version 1:
defmodule Demo do
defmodule Demo.Embed do
defstruct local: 0
end
defstruct name: "", embed: %Embed{}
end
defmodule Demo do
defmodule Embed do
defstruct local: 0
end
defstruct name: "", embed: %Embed{}
end
== 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
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.
Sorry I screwed up copying Example 1. The internal stuct, Embed, should not have been prepended with Demo. The error message reflects the error for the correct code but my cut & paste of the example afterwards forgot to cut it off.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAOMhEnwbM%3DfeN%2BWndyOUnXCO0VToG_uMKnjL-N7tQKPvjzjUDg%40mail.gmail.com.
Regarding #2 - Without a clearer understanding of the formal
specification of the language (ala #1) that tells me otherwise, I
still think (your corrected) Version #1 should be legal Elixir but
perhaps just requires a different mechanism for identifying when the
Module/Struct is fully defined. A two pass system could absolutely
still work this way.
variable = System.get_env("DEFINE_BAR")
defmodule Foo do
if variable in ~w(1 true) do
defmodule Bar do
end
end
end
While I personally think this behaviour is documented (because the two passes compilation is documented as part of the macro system as well as the fact that structs are expanded during compile time)
They're both fully closed at compile time in both
cases in that there is nothing more about the Demo.Embed struct to be
defined so references to it could be resolved at both compile and run
time.
Can you point me to where this issue of what is resolved at run time
vs compile time is documented?
I'm especially curious about your example code - is that legal elixir
if so, is my understanding correct that Foo.Bar is always
compiled but that its accessibility is still determined at run time?
This implies that you are supporting conditional compiling at run time
by allowing a different definition of Bar depending on the state of a
variable at run time. Is that correct?