I found a minimal example that shows one of the problem that I encounter while learning Elixir.
I write a script:
defmodule P do
defstruct a: 2
def geta(%P{a: a}), do: a
end
Use iex "filename"
to start an iex
session check that it works with P.geta(%P{a: 42})
Then I change the file to
defmodule P do
defstruct a: 2, b: 4
def getb(%P{a: a, b: b}), do: b
end
And when I launch iex
, it fails:
== Compilation error on file p.ex ==
** (CompileError) p.ex:3: unknown key :b for struct P
(elixir) src/elixir_map.erl:185: :elixir_map."-assert_struct_keys/5-lc$^0/1-0-"/5
(elixir) src/elixir_map.erl:62: :elixir_map.translate_struct/4
(stdlib) lists.erl:1353: :lists.mapfoldl/3
** (exit) shutdown: 1
(elixir) lib/kernel/parallel_compiler.ex:202: Kernel.ParallelCompiler.handle_failure/5
(elixir) lib/kernel/parallel_compiler.ex:185: Kernel.ParallelCompiler.wait_for_messages/8
(elixir) lib/kernel/parallel_compiler.ex:55: Kernel.ParallelCompiler.spawn_compilers/3
(iex) lib/iex/helpers.ex:168: IEx.Helpers.c/2
I can work around it by removing the content of the file except the definition, launching iex, pasting back the content of the file and relaunching iex. It looks to me as if the old struct is somehow cached by iex.
Two questions:
The main issue is you have functions on your struct module. That will cause problems like your seeing. You need to separate your struct and functions. You can nest the struct module inside your module if you want to.
defmodule P do
defmodule Data do
defstruct a: 2, b: 4
end
def geta(%Data{a: a}), do: a
def getb(%Data{b: b}), do: b
end
in iex:
iex> P.geta(%P.Data{a: 10})
10
iex> P.getb(%P.Data{a: 3, b: 24})
24