The method put_in when used with structs raises an UndefinedFuntionError get_and_update. Using put_in on a map works fine, and using it in its macro form works fine.
A little setup:
defmodule BugReport do
defstruct owner: %{}, details: "", severity: 1
end
defmodule Customer do
defstruct name: "", company: ""
end
And reproducing it:
struct_example = %BugReport{
owner: %Customer{ name: "Rufus the Dufus", company: "Int'l Conspiracy Corp"},
details: "OMG",
severity: 99999
}
map_example = %{
owner: %{
name: "Rufus the Dufus"
}
}
map_example = put_in(map_example, [:owner, :name], "Cory")
#=> map_example.owner.name == "Cory"
struct_example = put_in(struct_example.owner.name, "Cory")
#=> struct_example.owner.name == "Cory"
struct_example = put_in(struct_example, [:owner, :name], "Cory")
** (UndefinedFunctionError) undefined function BugReport.get_and_update/3
BugReport.get_and_update(%BugReport{details: "THE SSOFWAR EDOESNT EVEN WERK!!?!1111!!", owner: %Customer{company: "Int'l Conspiracy Corp", name: "Rufus the Dufus"}, severity: 99999}, :owner, #Function<17.51792600/1 in Kernel.get_and_update_in/3>)
(elixir) lib/kernel.ex:1721: Kernel.put_in/3
I am on the 1.2-rc1 branch
Yes because [:owner, :name] use Access which is not implemented for structs.
Another way to think about this is as follows:
put_in(struct_example.owner.name, "Cory")
translates to something like (pseudo-code):
put_in(struct_example, [Access.field(:owner), Access.field(:name)], "Cory")
while:
put_in(struct_example, [:owner, :name], "Cory")
translates to something like (pseudo-code):
put_in(struct_example, [Access.key(:owner), Access.key(:name)], "Cory")
They are different access rules. A struct has fields but it does not have keys generally speaking like a map or a keyword list would. Issue #4009 is about making all of this a bit more explicit.
Got it. Sorry working from an old version of the prag prog book but using a newer version of elixir!
Thanks for the link.
Sent from my iPhone
On Dec 29, 2015, at 4:06 PM, José Valim [email protected] wrote:
Another way to think about this is as follows:
put_in(struct_example.owner.name, "Cory")
translates to something like:put_in(struct_example, [Access.field(:owner), Access.field(:name)], "Cory")
while:put_in(struct_example, [Access.key(:owner), Access.key(:name)], "Cory")
They are different access rules. And a struct has fields but it does not have keys generally speaking like a map or a keyword list would. Issue #4009 is about making all of this a bit more explicit.—
Reply to this email directly or view it on GitHub.
Most helpful comment
Another way to think about this is as follows:
translates to something like (pseudo-code):
while:
translates to something like (pseudo-code):
They are different access rules. A struct has fields but it does not have keys generally speaking like a map or a keyword list would. Issue #4009 is about making all of this a bit more explicit.