Hi all, I have the following simple snippet but I got cyclic module usage error. Do you know how should I resolve the error?
defmodule Cycle do
alias Cycle.Handle
def hello(%Handle{resource: _resource}) do
:world
end
defmodule Handle do
defstruct resource: nil, reference: nil
def wrap_resource(resource) do
%__MODULE__{
resource: resource,
reference: make_ref()
}
end
end
end
The error is:
== Compilation error in file lib/cycle.ex ==
** (CompileError) lib/cycle.ex:16: Cycle.Handle.__struct__/0 is undefined, cannot expand struct Cycle.Handle. Make sure the struct name is correct. If the struct name exists and is correct but it still cannot be found, you likely have cyclic module usage in your code
lib/cycle.ex:16: (module)
The problem is that to compile Cycle, you need Cycle.Handle. Cycle.Handle does not really depends on Cycle. However, since both are in the same file, it still ‘sort of’ depends on it.
And as a result, the compiler is unable to continue.
The solution is to move the nested module to a separate file.
Cycle depends on Cycle.Handle at compile time (struct usage requires keys to be known), but Cycle.Handle cannot be compliled without Cycle being compiled. So you’re in a cyclic dependency. You’ll either need to use different files or put Cycle.Handle's definition before and outside of Cycle's definition.
We don’t need to be that drastic in fact, we can just move the Handle definition higher up in the file. This will work:
defmodule Cycle do
defmodule Handle do
defstruct resource: nil, reference: nil
def wrap_resource(resource) do
%__MODULE__{
resource: resource,
reference: make_ref()
}
end
end
def hello(%Handle{resource: _resource}) do
:world
end
end