我可以看到为什么参数化模块被如此使用,因为它们允许我们执行以下操作:
X = y:new("param").
X:action1().
X.get_property():
:感觉非常好。但是,这只是Erlang中的一个实验性功能,我听说它可能会被删除,所以我需要找到一个替代方案。
答案 0 :(得分:12)
参数化模块只不过是函数第一个参数的快捷方式。请参阅以下两个示例:
-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程序员正在使用的内容。
答案 1 :(得分:2)
为什么不能使用通常的方式,即将消息发送到与模块关联的(注册)服务器进程?
有问题的信息当然可以是您想要的任何内容,例如配置等。
你试图解决哪些问题无法以这种方式处理?