Les enregistrements sont du sucre syntaxique dans Erlang , élargi par le compilateur. La solution suivante, suggérée par @Dmitry, fonctionne, mais le compilateur ne l'optimisera pas à moins que vous ne passiez +inline, puisque l'astuce ici est de réellement créer un enregistrement :
g() -> (#something{})#something.email.
Le sucre syntaxique de ce disque sera étendu à : (utiliser erlc -E
)
g() ->
case {something,undefined,undefined,undefined} of
{something,_,_,rec0} ->
rec0;
_ ->
error({badrecord,something})
end.
et cela deviendra finalement : (utiliser 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.
En #something.email
de l'expression permet non seulement d'obtenir le champ "email" de l'enregistrement créé, mais aussi de vérifier que l'enregistrement transmis est bien formé. Ce test n'est actuellement pas optimisé par défaut. Heureusement, vous pouvez l'optimiser avec -compile([inline]).
dans votre module ou +inline
sur la ligne de commande.
La solution suivante est plus simple pour le compilateur :
f() -> element(#something.email, #something{}).
Le sucre syntaxique d'enregistrement (ici #quelquechose.email est l'index du champ email) se développera en :
f() ->
element(4, {something,undefined,undefined,undefined}).
Dans ce cas, nous ne demandons pas à Erlang de tester quoi que ce soit à propos de #something{}
un vrai disque de #something. Le compilateur optimise toujours les appels à element/2
fonction intégrée. Cela deviendra donc un jour :
{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.
Veuillez noter que la valeur par défaut de tout champ es undefined
sauf disposition explicite . En conséquence, votre code :
-record(something, {id :: integer(),
name :: string(),
email = undefined :: string() | undefined}).
est équivalent à :
-record(something, {id = undefined :: integer() | undefined,
name = undefined :: string() | undefined,
email = undefined :: string() | undefined}).
Pourtant, votre code semble signifier que l'id est toujours un integer()
et jamais undefined
De même, ce nom est toujours un string()
. C'est faux. Si c'est ce que vous voulez dire, vous devriez fournir une valeur par défaut différente de undefined
:
-record(something, {id = 0 :: integer(),
name = "" :: string(),
email :: string()}).
Seule la fourniture d'une valeur par défaut indiquera à dialyseur que l'identifiant et le nom ne peuvent jamais être undefined
.