我可以看到为什么参数化模块被如此使用,因为它们允许我们执行以下操作:
X = y:new("param").
X:action1().
X.get_property():
: 感觉很OO。但是,这只是 Erlang 中的一个实验性功能,我听说它可能会被删除,所以我需要找到一个替代方案。
最佳答案
参数化模块只不过是函数第一个参数的快捷方式。看这两个例子:
-module(y, [Name,Age]).
-compile(export_all).
action1() -> io:format("Hello, ~p!~n",[Name]).
get_age() -> Age.
运行:
1> c(y).
{ok,y}
2> X = y:new("Fred",22).
{y,"Fred",22}
3> X:action1().
Hello, "Fred"!
ok
4> X:get_age().
22
现在没有参数化的东西:
-module(y).
-compile(export_all).
action1([Name,_]) -> io:format("Hello, ~p!~n",[Name]).
get_age([_,Age]) -> Age.
运行它:
1> c(y).
{ok,y}
2> X = ["Fred",22].
["Fred",22]
3> y:action1(X).
Hello, "Fred"!
ok
4> y:get_age(X).
22
参数化模块的最大“优势”是您将携带状态的负担从变量转移到模块名称。对于不习惯“Erlang 方式”的人来说,这看起来要简单得多,但它与传统的代码风格相冲突。
这不仅仅是实验与否的问题。你抛弃了引用透明性,不可变变量的语义变得有点奇怪。一个很好的例子是假设您将以下函数添加到参数化模块:
ret_fn() -> fun(Age) -> Age + 5 end.
编译模块时,您会收到警告
./y.erl:8: Warning: variable 'Age' shadowed in 'fun'
.这是警告您在匿名函数的 head 子句中使用预定义变量的名称。然而,快速浏览ret_fn/0
函数绝对没有显示该变量来自何处的迹象。现在假设您使用变量
Name
用于任何其他目的;你会得到一个运行时错误告诉你** error: no match of right hand side value < ... >
.我要说的一点是,参数化模块减少了您需要做的输入量,但以牺牲逻辑简单性为代价。不仅为您,也为任何其他 Erlang 程序员处理您的代码。
最重要的是,dialyzer、TypEr、tidiers 等工具并不能保证支持这些惯用语。这些工具也非常有用!不要解雇他们。 (编辑:较新版本的 Erlang (R13B04+) 现在保证支持)
参数化模块的最佳替代方案是避免使用它们并使用 mochiweb 之外的所有其他 Erlang 程序员正在使用的东西。
关于erlang - Erlang 中的参数化模块有哪些替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2291155/