-module(structs).
-export([new_person/1, main/0]).
-record(person, {name, age = 0}).
new_person(Name) ->
#person{name=Name, age=42}.
main() ->
% This syntax creates a new struct
io:format("~p~n", [#person{name="Bob", age=20}]),
% You can name the fields when initializing a struct
io:format("~p~n", [#person{name="Alice", age=30}]),
% Omitted fields will be zero-valued
io:format("~p~n", [#person{name="Fred"}]),
% An & prefix yields a pointer to the struct
P1 = #person{name="Ann", age=40},
Ptr1 = erlang:make_ref(),
io:format("~p~n", [Ptr1]),
% It’s idiomatic to encapsulate new struct creation in constructor functions
io:format("~p~n", [new_person("Jon")]),
% Access struct fields with a dot
S = #person{name="Sean", age=50},
io:format("~p~n", [S#person.name]),
% You can also use dots with struct pointers - the pointers are automatically dereferenced
SP = &S,
io:format("~p~n", [SP#person.age]),
% Structs are mutable
NewSP = setelement(2, SP, 51),
io:format("~p~n", [NewSP#person.age]),
% If a struct type is only used for a single value, we don’t
% have to give it a name. The value can have an anonymous
% struct type.
Dog = #{name => "Rex", isGood => true},
io:format("~p~n", [Dog]).