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

Erlang Function call with default values and or without specific order

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

Erlang 版本:

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]

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]

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

  • 带有可选参数的 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}).

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

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

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

P.P.S。如果您传递未知选项,它将抛出异常。