Piplelining structs (key access)

I recently changed some of the internals of an app, moving from Maps to Structs. Where some of my pipelines relied on accessing particular keys in a map, moving to Structs obviously breaks all these

(UndefinedFunctionError) function Foo.fetch/2 is undefined (Foo does not implement the Access behaviour

To make a long story short: what is the preferred way of accessing struct keys in a pipeline, without having to implement anything (like access behaviour) on the struct?

%{“foo” => “bar”}
|> Map.get(“foo”)
# => “bar”

%Foo{foo: “bar”}
|> ??? # get the ‘foo’ key somehow?
# => “bar”

I feel a bit silly asking for what I think should be fairly basic, but can’t find the answer…

The only way I am aware of, is to use a helper function or to make them a map again:

%Foo{foo: "bar"}
|> (fun %{foo: val} -> val end).()

or

%Foo{foo: "bar"}
|> Map.from_struct()
|> Map.get(:foo)

You won’t be able to use stringified keys either way.

Structs are actually maps underneath:

%{__struct__: :"Elixir.Foo", foo: "bar"} == %Foo{foo: "bar"}
true

So you can perform most of map operations on them as is:

%Foo{foo: "bar"}
|> Map.get(:foo)
"bar"
1 Like

Still works. The major difference is that structs don’t by default implement the entirety of the Access behaviour. For example foo[:foo] wouldn’t work.

Structs are bare maps underneath

2 Likes

Yes, you are right. Map.get/2 does not rely on the Access-behaviour.

So whatever causes the errormessage of the OP seems not to be related to the examples he gave.

@peerreynders: Thanks so much for pointing this out, it turns out the errors come for use of brackets elsewhere in the code.

Elixir is great great language, but the community is da real MVP. Fantastic.

2 Likes