d4mr
If structs are just maps underneath then how does pattern matching to ensure struct type work?
For example:
defmodule Attendee do
defstruct name: "", paid: false, over_18: true
def may_attend_after_party(attendee = %Attendee{}) do
attendee.paid && attendee.over_18
end
def may_attend_after_party_without_struct(attendee = %{name: "", paid: false, over_18: true}) do
attendee.paid && attendee.over_18
end
end
iex(1)> Attendee.may_attend_after_party(%Attendee{name: "John"})
false
iex(2)> Attendee.may_attend_after_party(%Attendee{name: "John", paid: true})
true
iex(3)> Attendee.may_attend_after_party_without_struct(%Attendee{name: "John", paid: true})
** (FunctionClauseError) no function clause matching in Attendee.may_attend_after_party_without_struct/1
The following arguments were given to Attendee.may_attend_after_party_without_struct/1:
# 1
%Attendee{name: "John", over_18: true, paid: true}
structwtf.exs:8: Attendee.may_attend_after_party_without_struct/1
iex(4)>
%Attendee{} evaluates to %Attendee{name: "", over_18: true, paid: false}, and if structs are just maps underneath, then shouldn’t the behaviour remain similar?
Trending in Questions
Hey guys,
I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly
Do you guys have any suggestions what is the best prac...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
Anyone here using Honeybadger?
My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of
Bandit.HTTPError...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 8- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
al2o3cr
Your example code omits the definition of
Attendee.may_attend_after_party_without_struct/1; I trieddef may_attend_after_party_without_struct(attendee = %{}) doand it worked, so you’ll need to provide more information about what behavior you’re expecting.d4mr
My bad, updated the example
ityonemo
Structs have a magic hidden key
__struct__which gets implicitly matched on when you prepend the struct module in between % and {. The default key/values are not filled in for matches, just the struct key.Eiji
In fact they are!
What happen here? First of all the
structis not valid only because “some map” have__struct__key even if value is valid. The map needs to have all keys available for suchstruct. The rest is sugar when inspecting.The
%{}syntax or more precisely%special form is just handled differently. Just to imagine:The only difference between
add/2andadd_alt/2is that first returns just the result and second wraps it in “ok-tuple” which is useful for error handling.If you check how it’s
ASTyou would see that’s almost the same as in my example:So inside
%special form simple map (%{}) is used. The special form simply adds to yourmapastructkeys with their default values ornilif default value is not specified.For more information see: %/2 special form
IloSophiep
I’m not certain, but i think the way you pattern match in your function “without struct” is not what you intend to do. What you have is:
That means only maps are “matched”, that
I think what you actually want is just matching the existence of the keys, as in the following
See how i tell the function head that i want the map to contain those three keys (
:name,:paidand:over_18), but i discard the value of those keys - that way i “allow” any value.Is this what you were hoping for?
d4mr
I understand your pattern matching snippet, and in fact that is what I would expect to work.
However, because structs are matched in this manner:
and because
%Attendee{}evaluates to%Attendee{name: "", over_18: true, paid: false}I expected the other behaviour to work.However @ityonemo has given a very concise answer about why this works and @Eiji has provided an amazing demonstration of the fact.
Thanks a lot! This was my first interaction with the Elixir community, and makes me very happy to be a part of it
IloSophiep
Do you mean those are the default values, if you create an empty Attendee struct? Because as with maps - at least i think - the pattern matching for “apparently empty stuff” is maybe not instantly obvious:
As you can see, the “empty map”
%{}doe not only match empty maps, but any map. That tends to be very useful for the typical use. But that also means your usage ofdoes not mean you are trying to match an empty attendee or a default attendee. It means you are matching any attendee struct, no matter the contents.
I hope that was clear - does it make sense to you, the way i described it?
al2o3cr
“Evaluates to” is the gotcha here, the arguments of a function are always a “match context” which has special properties - this:
and this:
both result in the same function that matches a map with a
single_valuekey and bindswhole_argandv.This is not the same
=that you get when writing those statements alone:I suspect this is why it’s a common convention to write pattern-matches on structs on the left-hand side:
as it’s clearly distinguishable from the “evaluation”
=.