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
Hello!
Suppose you are building workflow (order / task / payment) processing system with the following requirements:
Each workflow con...
New
I’m aware of 2 such projects, are there others?
git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
Hi all,
I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
Hi everyone.
My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
Hi,
we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
Hi all, I’m new here and would like to hear peoples views on my Elixir/Phoenix based game-engine! :smiley:
Mutonex gamedesign was finish...
New
Hello
I’ve been coding in Elixir for almost two years now because of my current job where we implemented Elixir in our application. But ...
New
Other Trending Topics
Hey there,
I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first.
...
New
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself.
My main conc...
New
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly)
AI dream has many faces, but general...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #ai
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #blog-post
- #ecto-query
- #elixirconf-us
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #security
- #hex










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”
=.