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