gpt4 book ai didi

erlang - 有没有办法对默认记录值进行查找?

转载 作者:行者123 更新时间:2023-12-02 07:14:41 25 4
gpt4 key购买 nike

给定一条记录

-record(something, {id                :: integer(),
name :: string(),
email = undefined :: string() | undefined}).

有没有办法获取字段的默认值,在此示例中获取 #something.email 默认为未定义的事实?

最佳答案

记录是 Erlang 中的语法糖,由编译器扩展。 @Dmitry 建议的以下解决方案是有效的,但编译器不会优化它,除非您传递 +inline,因为这里的技巧是真正创建一条记录:

g() -> (#something{})#something.email.

这样的记录语法糖将扩展为:(使用erlc -E)

g() ->
case {something,undefined,undefined,undefined} of
{something,_,_,rec0} ->
rec0;
_ ->
error({badrecord,something})
end.

这最终将变成:(使用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.

表达式中的#something.email部分不仅意味着获取所创建记录的电子邮件字段,还意味着检查传递的记录是否格式良好。该测试目前默认未优化。幸运的是,您可以在模块中使用 -compile([inline]). 或在命令行上使用 +inline 对其进行优化。

以下解决方案对于编译器来说更简单:

f() -> element(#something.email, #something{}).

记录语法糖(这里#something.email是email字段的索引)将扩展为:

f() ->
element(4, {something,undefined,undefined,undefined}).

在这种情况下,我们不会告诉 Erlang 测试有关 #something{} 是否为正确的 #something 记录的任何内容。编译器始终优化对 element/2 内置函数的调用。所以这最终会变成:

{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.

请注意,除非明确提供,否则任何字段的默认值都是未定义。因此,您的代码:

-record(something, {id                :: integer(),
name :: string(),
email = undefined :: string() | undefined}).

相当于:

-record(something, {id    = undefined :: integer() | undefined,
name = undefined :: string() | undefined,
email = undefined :: string() | undefined}).

但是,您的代码似乎意味着 id 始终是 integer() 并且永远不会 undefined,同样,该名称始终是 string()。这是不真实的。如果这就是您的意思,您应该提供一个与 undefined 不同的默认值:

-record(something, {id    = 0   :: integer(),
name = "" :: string(),
email :: string()}).

仅提供默认值即可告诉dialyzer id 和 name 永远不能未定义

关于erlang - 有没有办法对默认记录值进行查找?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18116330/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com