#How to use get_in with structs

11 messages · Page 1 of 1 (latest)

broken frigate
#

Hello, I asked the question earlier but have lost where I asked it - a question here sounds better though so here it is:

defmodule Inner do
  defstruct prop: nil
end

defmodule Outer do
  defstruct inner: %Inner{}
end
a = %Outer{inner: %Inner{prop: "Hello"}}
get_in(a, ["inner", "prop"])

Results in the error:

** (UndefinedFunctionError) function Outer.fetch/2 is undefined (Outer does not implement the Access behaviour. If you are using get_in/put_in/update_in, you can specify the field to be accessed using Access.key!/1)
    Outer.fetch(%Outer{inner: %Inner{prop: "Hello"}}, "inner")
    (elixir 1.15.4) lib/access.ex:305: Access.get/3
    (elixir 1.15.4) lib/kernel.ex:2792: Kernel.get_in/2
    #cell:5ey2h6xnqxhcq555jtahmipsngfqtwfe:1: (file)

My mental model is that structs are just sugar around maps, so why is there a behavioral difference when using get_in?

tropic loom
#

I think it was explained earlier that structs don't implement the Access protocol so that's why it doesn't work. Specifically for get_in you could express the samething as a.inner.prop and it's shorter + gives an appropriate error if inner doesn't have a field called prop.

broken frigate
#

Thank you, sorry for the double up - I can't for the life of me find the original thread where i posted the q

vale flame
#

if you wish to stick in with get_in

broken frigate
#

thanks, i will play around some more

timber condor
broken frigate
#

Thanks, what is the best way to consume this?

broken frigate
#

ok I put that into a livebook and have tried this:

defmodule Inner do
  use Lexical.StructAccess
  defstruct prop: nil
end

defmodule Outer do
  use Lexical.StructAccess
  defstruct inner: %Inner{}
end
a = %Outer{inner: %Inner{prop: "Hello"}}
get_in(a, ["inner", "prop"])

and this is returning nil - good news is that it doesn't complain about Access not being implemented anymore

#

ah nvm i got it 😄 get_in(a, [:inner, :prop]) work since keys are atoms

timber condor
#

btw, you can just copy that into your project and dump the Lexical prefix