Andres

Andres

Trying to understand the source code of the intersection function of the Mapset module

Hello.

I apologize if my questions are very basic.
I am trying to understand the source code of the intersection function of the Mapset module.
I have encountered many behaviors that I do not understand.

First I would like to understand the following behavior:

a = MapSet.new([1, 2, 3, 5])
b = MapSet.new([3, 4, 5])
c = %MapSet{map: a}

IO.inspect(c)
# #MapSet<[:__struct__, :map, :version]>

I searched in Google and in my Elixir books for that result and unfortunately I did not find any relevant information.

I can see that in #MapSet <[: __ struct__,: map,: version]> there is a :map atom key.
The intersection function makes use of that key.

If I try to change the :map key to another name I get a KeyError

d = %MapSet{other: a}
# ** (KeyError) key :other not found
#    (elixir) expanding struct: MapSet.__struct__/1
#    main.exs:34: (file)

Intersection function:

a = MapSet.new([1, 2, 3, 5])
b = MapSet.new([3, 4, 5])
defp order_by_size(map1, map2) when map_size(map1) > map_size(map2), do: {map2, map1}
defp order_by_size(map1, map2), do: {map1, map2}

# If I inspect the parameters of the intersection function 
# I get the following results:
def intersection(%MapSet{map: map1} = map_set, %MapSet{map: map2}) do
  IO.inspect(map1)
  # %{1 => [], 2 => [], 3 => [], 5 => []}
  # How is it possible that a Map was generated with the MapSet values as its keys?

  # #MapSet<[1, 2, 3, 5]>
  IO.inspect(map_set)

  # %{3 => [], 4 => [], 5 => []}
  IO.inspect(map2)

  # I understand this part of the code 。^‿^。
  {map1, map2} = order_by_size(map1, map2)

  # I would like to know why it is possible to interact with two different data structures:
  # #MapSet <[1, 2, 3, 5]> and % {1 => [], 2 => [], 3 => [], 5 = > []}
  # Why we surround map_set with a Map% {} struct and still return a MapSet?
  %{map_set | map: Map.take(map2, Map.keys(map1))}
end

In the end it seems that a Mapset is an undercover Map. :male_detective:
Thanks.

Most Liked

LostKobrakai

LostKobrakai

That’s exactly what it is, hence the name “MapSet”. But a map alone cannot guarantee that the constraints of being a set are abided for. There simply isn’t a native set datatype on the beam. If you look at MapSet.t the type for MapSets you’ll notice that it’s a “opaque” type. This means you’re not supposed to directly interact with any MapSet other than by using functions on the MapSet module. It alone can guarantee that you’re not breaking the data from being a set. Also in theory this allows MapSet to change the implementation at any time without breaking code using them.

Andres

Andres

Hello @LostKobrakai

Very useful information. Thanks so much for your answer.

Where Next?

Popular in Questions Top

Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
Mooodi
Given a string, how can I get access to its character by index? Enum.at("my_string", 2) doesn't work. Or rather, not char, but a substr...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
William
I would like to know that is there any online source for learning Phoenix Framework for building E-Commerce Store? Any advantage on build...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

We're in Beta

About us Mission Statement