类似的问题被问到Parameterised Modules in Erlang,它是关于"什么"。我的问题是关于"为什么"?
OTP Technical Board - Decisions affecting R16包含董事会关于此问题的决定,但我不知道决定背后的原因。
Stateful Module in Programming Erlang 2ndEdition by Joe Armstrong详细介绍了此功能,但我没有看到作者的态度。
如果我们阅读官方文件Function Calls,我们会看到此功能是故意浏览的。事实上,官方文档强烈反对使用此功能,请参阅efficiency function calls。如果是这样,为什么乔·阿姆斯特朗在他的书中提到了这样的特征呢?
我认为这个功能非常棒。如上所述,我的客户端代码可能如下所示
Obj:find(Key),
Obj:is_key(Key),
然后,我们不关心Obj
是由dict:new()
创建还是gb_tree:new()
,不幸的是,dict
和gb_tree
不共享一致的接口,例如我们有gb_tree:lookup
而不是gb_tree:find
。
答案 0 :(得分:6)
我无法告诉你在控制一切的Great Cabal中的讨论内容,但我可以告诉你为什么我从未考虑使用此功能的原因:
它引入了句法复杂性和语义歧义,但没有给我新的超级大国。
复杂度:
X
的属性Foo
现在等于10或20?" dict:is_key(Value, Thingy)
然后Thingy:is_key(Value)
呢?dict:is_key(Key, Foo:get_value(Key2))
这样的代码?" 歧义:
这引入了不透明状态(坏)而不是ADT(好的,我们已经拥有的东西)。
Foo:is_key(Key)
与dict:is_key(Key, Foo)
之间没有太大区别。除了我在第一次阅读时某些的事实,即使在完全没有上下文的情况下,在第二版中操作的数据对象肯定是一个字典。Erlang的符号赋值(又名"单一作业")很棒,为什么会破坏它?
答案 1 :(得分:3)
还有其他问题:
当我写Foo:bar(42)
Foo
时,bar/1
可能只是模块名称,也可能是元组模块,但我没有看到区别。这意味着我可能会调用bar/2
或newTutorial[0]['header'] = 'some header';
newTutorial[0]['text'] = 'some text';
newTutorial[1]['header'] = 'some header';
newTutorial[1]['text'] = 'some text';
...
。
我可以用不同的方式调用相同的函数。
由于 arity 不同,可能很难将函数中的错误与调用联系起来。
还有更多。我认为当我们摆脱参数化模块时,我们没有摆脱元组模块,这是一种耻辱。它们最初只是实现参数化模块的一种hacky方式。