使用默认值和/或没有特定顺序的 Erlang 函数调用

cas*_*lic 2 erlang function clojure default-arguments

我是 Erlang 新手,试图找出函数调用的默认值的最佳方法,这需要多个变量和/或也不想按特定顺序输入参数。我目前正在使用这种基于 Clojure 方式的松散格式。在Erlang中是否有更好的方式或方法来实现这一点?我还提供了一个 Clojure 示例作为参考:

二郎版本:

some_function_with_defaults() ->
    some_function_with_defaults(#{}).

some_function_with_defaults(Map) ->
    Defaults = #{
                arg1 => 0, % arg1 default value
                arg2 => 1, % arg2 default value
                arg3 => 2  % arg3 default value
              },

  Arguments = maps:merge(Defaults,Map),

  #{arg1 := Arg1} = Arguments,
  #{arg2 := Arg2} = Arguments,
  #{arg3 := Arg3} = Arguments,

  %% Do something with arguments
  [Arg1,Arg2,Arg3].

%% Example call using only defaults
%% some_function_with_defaults().
%%
%% [0,1,2]

%% Example call specifying a specific value
%% some_function_with_defaults(#{arg1 => 99}).
%%
%% [99,1,2]
Run Code Online (Sandbox Code Playgroud)

Clojure 参考:

(defn some-function-with-defaults 
    [
     & {:keys
        [
         arg1
         arg2
         arg3

        ]
        :or
        {
         arg1 0 ;; arg1_default_value
         arg2 1 ;; arg2_default_value
         arg3 2 ;; arg3_default_value
        }
       }
  ]

  ;; Do something with arguments
  [arg1,arg2,arg3]
)

;; Example call using only defaults
;; (some-function-with-defaults)
;; 
;; [0,1,2]

;; Example call specifying a specific value
;; (some-function-with-defaults :arg1 99)
;;
;; [99,1,2]
Run Code Online (Sandbox Code Playgroud)

dan*_*kin 5

在地图到来之前我经常看到的方法之一是:

  • 带有可选参数的 proplist
  • 使用默认值记录
  • 函数从 proplist 中获取值并将其放入记录中。
-record(options, {
    opt_int = 42     :: integer(),      % default is 42
    opt_bool = false :: boolean(),      % default false
    opt_atom         :: undefined | val % default undefined
}).
parse_opts(Opts) ->
    parse_opts(Opts, #options{}).

parse_opts([], Res) ->
    Res;
parse_opts([{opt_int, Val} | RestOpts], Res) when is_integer(Val) ->
    parse_opts(RestOpts, Res#options{opt_int = Val});
parse_opts([{opt_bool, Val} | RestOpts], Res) when is_boolean(Val) ->
    parse_opts(RestOpts, Res#options{opt_bool = Val});
parse_opts([{opt_atom, Val} | RestOpts], Res) when Val == undefined; Val == val ->
    parse_opts(RestOpts, Res#options{opt_atom = Val}).
Run Code Online (Sandbox Code Playgroud)

parse_opts([{opt_int, 55}])会给你#options{opt_int = 55, opt_bool = false, opt_atom = undefined}

这有点尴尬,主要是因为记录是元组的编译时语法糖。不过,您可以使用地图做更优雅的事情。

PS 没有对此进行测试,因此可能包含一些错误。

PPS 如果你传递未知选项,它会抛出异常。