Tuples, Records & Maps
Records are tuples at runtime: {person, "Ann", 0, undefined}.
13.1 Records — named tuples (compile-time)
Records are tuples at runtime: {person, "Ann", 0, undefined}. Share definitions through .hrl header files:
In the shell: rr("person.hrl"). loads records; rd(person, {name, age}). defines one.
-record(person, {name, age = 0, email = undefined}).
new_person() -> #person{name = "Ann", age = 30}.
P = #person{name = "Ann"},
P#person.name, % "Ann" — field access
P2 = P#person{age = 31}, % update
#person{name = Name} = P, % pattern match
is_record(P, person), % true (also usable in guards)
record_info(fields, person). % [name,age,email]%% person.hrl
-record(person, {name :: string(), age = 0 :: non_neg_integer()}).
%% in a module
-include("person.hrl").13.2 Maps (OTP 17+)
Guards: is_map/1, is_map_key/2, map_get/2, map_size/1.
M = #{name => "Ann", age => 30},
#{name := Name} = M, % match: := for existing keys
M2 = M#{age := 31}, % update existing key (crashes if absent)
M3 = M#{city => "Oslo"}, % insert or update
maps:get(name, M), % "Ann" (badkey error if missing)
maps:get(city, M, unknown), % default value
maps:find(name, M), % {ok,"Ann"} | error
maps:put(k, v, M), maps:remove(age, M),
maps:is_key(name, M), map_size(M),
maps:keys(M), maps:values(M), maps:to_list(M), maps:from_list([{a, 1}]),
maps:merge(#{a => 1}, #{b => 2}),
maps:merge_with(fun(_K, V1, V2) -> V1 + V2 end, #{a => 1}, #{a => 2}), % OTP 24+
maps:map(fun(_K, V) -> V * 2 end, #{a => 1}),
maps:filter(fun(_K, V) -> V > 1 end, #{a => 1, b => 2}),
maps:fold(fun(K, V, Acc) -> [{K, V} | Acc] end, [], M),
maps:update_with(count, fun(C) -> C + 1 end, 1, #{}),
maps:with([name], M), maps:without([age], M),
maps:groups_from_list(fun(X) -> X rem 2 end, [1, 2, 3]), % OTP 25+
maps:iterator(M), maps:next(It).13.3 Records vs maps
compile-time fields, fast need .hrl sharing typos caught at compile time flexible, JSON-like used heavily in OTP state preferred for new code / APIs