erlang - Is there a way to do lookups on default record values? -
given record
-record(something, {id :: integer(), name :: string(), email = undefined :: string() | undefined}).
is there way default values fields, in example getting fact #something.email
defaults undefined?
records syntactic sugar in erlang, expanded compiler. following solution, suggested @dmitry, works, compiler not optimize away unless pass +inline, since trick here create record:
g() -> (#something{})#something.email.
such record syntactic sugar expanded to: (use erlc -e
)
g() -> case {something,undefined,undefined,undefined} of {something,_,_,rec0} -> rec0; _ -> error({badrecord,something}) end.
and become: (use erlc -s
)
{function, g, 0, 4}. {label,3}. {line,[{location,"test.erl",10}]}. {func_info,{atom,test},{atom,g},0}. {label,4}. {move,{literal,{something,undefined,undefined,undefined}},{x,0}}. {test,is_tuple,{f,5},[{x,0}]}. {test,test_arity,{f,5},[{x,0},4]}. {get_tuple_element,{x,0},0,{x,1}}. {get_tuple_element,{x,0},3,{x,2}}. {test,is_eq_exact,{f,5},[{x,1},{atom,something}]}. {move,{x,2},{x,0}}. return. {label,5}. if_end.
the #something.email
part of expression not means getting email field of created record, checking passed record formed. test not optimized default. fortunately, can optimize -compile([inline]).
in module or +inline
on command line.
the following solution simpler compiler:
f() -> element(#something.email, #something{}).
record syntactic sugar (here #something.email index of email field) expand to:
f() -> element(4, {something,undefined,undefined,undefined}).
in case, not tell erlang test #something{}
being proper #something record. compiler optimizes calls element/2
built-in function. become:
{function, f, 0, 2}. {label,1}. {line,[{location,"test.erl",7}]}. {func_info,{atom,test},{atom,f},0}. {label,2}. {move,{atom,undefined},{x,0}}. return.
please note default value field is undefined
unless explicitly provided. result, code:
-record(something, {id :: integer(), name :: string(), email = undefined :: string() | undefined}).
is equivalent to:
-record(something, {id = undefined :: integer() | undefined, name = undefined :: string() | undefined, email = undefined :: string() | undefined}).
yet, code seems mean id integer()
, never undefined
, , likewise name string()
. untrue. if mean, should provide default value different undefined
:
-record(something, {id = 0 :: integer(), name = "" :: string(), email :: string()}).
only providing default value tell dialyzer id , name can never undefined
.
Comments
Post a Comment