如何在erlang中使用record参数定义函数

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类型?

Ste*_*ski 6

直接在函数参数列表中构造记录通常很方便,这也会强制该参数具有所需的记录类型.例如,我们可以稍微修改一下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)

两者NameId随后可用于函数体中使用.

另一件事:不要将atom null用作记录字段的默认值.Erlang记录字段的默认值是atom undefined,因此您应该使用它.这比null在语言中定义自己的概念更可取.