minhajuddin
Defmap - embed maps into a module for faster/easier lookups. Feedback please
Defmap is a utility which allows you to embed a map into a module for faster/easier lookups.
Most Liked
sasajuric
I’m not sure you need a lib and a macro for this. You can get the same thing with something like this (untested):
defmodule Foo do
for {code, message} <- {400 => "Bad Request", 401 => "Unauthorized", 403 => "Forbidden"} do
def get(unquote(code)), do: {:ok, unquote(message)}
end
def get(_), do: :error
end
I occasionally use this technique.
bbense
Well, there can be some performance advantages in functional heads vs just looking things up in a map. This is more or less the way unicode support is implemented in Elixir core.
I think I’d like this more if it did not use the Map get as the function name and I’d really like it a lot more if it wasn’t called Defmap. The function is really just get_constant, or even just constant or attribute. It’s a generic tool for exposing module attributes as functions. Map is just a convenient way to structure the input, you aren’t defining a Map in any practical sense at all.
The only thing wrong with this is actually the hardest part of programming, naming stuff. I think what it does is useful.
OvermindDL1
Ah that’s cool. 
minhajuddin
Thanks for all the feedback guys 
I have benchmarked the simple map implementation from @Eiji
Elixir 1.3.3
Benchmark suite executing with the following configuration:
warmup: 2.0s
time: 5.0s
parallel: 1
Estimated total run time: 14.0s
Benchmarking defmap...
Benchmarking plainmap...
Name ips average deviation median
defmap 4.87 K 205.17 μs ±6.77% 201.00 μs
plainmap 4.46 K 224.04 μs ±11.79% 215.00 μs
Comparison:
defmap 4.87 K
plainmap 4.46 K - 1.09x slower
The difference is performance is not huge. However, there is a huge difference in memory usage. I checked the memory usage of the defmap version using :observer.start (Please recommend a good memory profiling tool, I didn’t know any
) and defmap used ~43mb of memory whereas plainmap used ~200mb, This was my initial assumption as for every lookup with the map implementation we are instantiating a full map and then selecting one value from it. You can checkout the test implementation @ https://github.com/minhajuddin/defmap_test
Eiji
Ok, now I see your point.
Thanks for performance testing, they give me a lot to think about.
I have a feature request:
more configuration - allow to send opts like:
defmodule MyProject do
YourLibrary.your_macro(my_first_map)
YourLibrary.your_macro(my_second_map, [caller: :get_value])
YourLibrary.your_macro(my_third_map, [private: true])
end
to allow define multiple embed maps (also private maps) into one module with different callers.
Your default configuration config.exs:
config :defmap, :default_opts,
caller: :get,
private: false







