Joh*_*rek 1 erlang module record
我想定义我的函数输入的结构.
这个模块定义了我的函数(它的一部分是伪代码):
-module(my_service).
-export([my_function/2]).
-type my_enum() :: 1 | 2 | 5.
-record(my_record, {id = null :: string(), name = null :: string(), myType = null :: my_enum()}).
-spec my_function(MyValue#my_record) -> Result#my_record.
my_function(ClientRequest, MyValue) when is_record(Entry, my_record) ->
Response = client:request(get, "http://www.example.com/api?value=" + MyValue#my_record.name),
case Response of
{ok, Status, Head, Body} ->
Result = parse_response(Body, my_record);
Error ->
Error
end.
Run Code Online (Sandbox Code Playgroud)
这就是我想要的方式:
-module(test1).
-import(io, [format/2]).
main(_) ->
application:start(inets),
MyTestValue = #my_record{name => "test value", myType => 2},
X = my_service:my_function(MyTestValue),
io:format("Response: ~p", [X]).
Run Code Online (Sandbox Code Playgroud)
那么,任何想法如何强制函数输入的类型为my_record类型?
直接在函数参数列表中构造记录通常很方便,这也会强制该参数具有所需的记录类型.例如,我们可以稍微修改一下my_function/2
这样的:
my_function(ClientRequest, #my_record{name=Name}=MyValue) ->
Response = client:request(get, "http://www.example.com/api?value=" ++ Name),
case Response of
{ok, Status, Head, Body} ->
Result = parse_response(Body, MyValue);
Error ->
Error
end.
Run Code Online (Sandbox Code Playgroud)
注意我们如何模式匹配第二个参数MyValue
:我们不仅断言它是一个#my_record{}
实例,而且我们同时也将它的name
字段提取到Name
变量中.这很方便,因为我们Name
在函数体的第一行使用它.请注意,我们还保留参数名称,MyValue
因为我们将其传递给parse_response/2
函数体.如果我们不需要它,我们可以像这样编写函数头:
my_function(ClientRequest, #my_record{name=Name}) ->
Run Code Online (Sandbox Code Playgroud)
这仍然会产生强制第二个参数为类型的预期效果#my_record{}
,并且仍然会提取Name
.如果需要,您可以以类似的方式提取其他字段:
my_function(ClientRequest, #my_record{name=Name, id=Id}) ->
Run Code Online (Sandbox Code Playgroud)
两者Name
并Id
随后可用于函数体中使用.
另一件事:不要将atom null
用作记录字段的默认值.Erlang记录字段的默认值是atom undefined
,因此您应该使用它.这比null
在语言中定义自己的概念更可取.