Good evening, morning, afternoon!
I was
wondering with my team what is the best way of acessing keys from
structs, and we have the dynamic way. That's is something like:
def create_order!(item, user) do
Repo.insert!(%Order{
user_id: user.id,
user_email: user.email,
user_shipping_address_id: user.user_shipping_address_id,
total_price: item.price,
total_weight: item.weight,
quantity: 1
})
end
This
dynamic way is very short and direct to the point. However, if there's
any typo on the key, if we don't have any unit test, it will show up
during the runtime.
Elixir then, provide us the pattern matching way:
def create_order!(
%Item{
price: item_price,
weight: item_weight
},
%User{
id: user_id,
email: user_email,
shipping_address_id: user_shipping_address_id
}
) do
Repo.insert!(%Order{
user_id: user_id,
user_email: user_email,
user_shipping_address_id: user_shipping_address_id,
total_price: item_price,
total_weight: item_weight,
quantity: 1
})
end
We
split up in two steps, one to bind the key value to a variable, then
another step to build the new struct. This extra step make the code more
verbose generating 2*n lines where `n` is the number of attributes you
want to assign.
We're discussing how we could
make the code shorter and straight to the point like the dynamic
version, we thought in something like creating functions to get values
from the keys. Something like:
def create_order!(item, user) do
Repo.insert!(%Order{
user_id: User.id(user),
user_email: User.email(user),
user_shipping_address_id: User.shipping_address_id(user),
total_price: Item.price(item),
total_weight: Item.weight(item),
quantity: 1
})
end
Using
functions like this, we have compile time checks that we didn't make
any typo and also is shorter and straightforward like the dynamic
version.
The downsinde is creating functions like this, it's a
little bit boring and repetitive. I was thinking if there's any space
for a shorthad syntax.
Today we have a shorthand syntax to update key values like this:
%User{user | email: "aaaa"}
I wonder if we can have similar syntax to get a value from a key. Suggestions:
%User{user | :email}
%User{user |> :email}
%User{user -> :email}
Then we could write:
def create_order!(item, user) do
Repo.insert!(%Order{
user_id: %User{user -> :id},
user_email: %User{user -> :email},
user_shipping_address_id: %User{user -> :user_shipping_address_id},
total_price: %Item{item -> :price},
total_weight: %Item{item -> :weight},
quantity: 1
})
end
What do you folks think? Does it make sense?
--