1

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:

  • Is this a bug or a design decision?
  • Is there a more clever way to work around it?
lc2817
  • 3,722
  • 16
  • 40
  • 2
    You're launching a brand new `iex "filename"` after changing the file to include `:b` right? I can't reproduce this on my system. – Dogbert Jun 30 '16 at 04:32
  • Like @Dogbert I tried this and I can't reproduce the issue on my system. Can you share more detailed reproduction steps? – Onorio Catenacci Jun 30 '16 at 12:51
  • I do that yes and I use Interactive Elixir (1.2.3) - press Ctrl+C to exit (type h() ENTER for help) – lc2817 Jul 01 '16 at 01:21
  • Perhaps a longshot, but try `r P` in your iex. If you've saved the file, it should recompile and reload the module. – Cody Poll Jul 01 '16 at 02:44

1 Answers1

0

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
TattdCodeMonkey
  • 155
  • 1
  • 7