Module 我怎样才能有一个;“私人”;Erlang模块?

Module 我怎样才能有一个;“私人”;Erlang模块?,module,erlang,Module,Erlang,我更喜欢处理长度小于1000行的文件,因此我考虑将一些Erlang模块分解成更小的部分 有没有一种方法可以在不扩展我的库的公共API的情况下实现这一点 我的意思是,任何时候有一个模块,任何用户都可以做module:func\u exported\u来自\u模块。据我所知,让某些东西真正成为私有的唯一方法是不从任何模块导出它(甚至可以戳出漏洞) 所以,如果从技术上讲,没有办法实现我所追求的目标,那么是否有一个惯例? 例如,Python类中没有私有方法,但惯例是在\u my\u private\u方

我更喜欢处理长度小于1000行的文件,因此我考虑将一些Erlang模块分解成更小的部分

有没有一种方法可以在不扩展我的库的公共API的情况下实现这一点

我的意思是,任何时候有一个模块,任何用户都可以做
module:func\u exported\u来自\u模块
。据我所知,让某些东西真正成为私有的唯一方法是不从任何模块导出它(甚至可以戳出漏洞)

所以,如果从技术上讲,没有办法实现我所追求的目标,那么是否有一个惯例? 例如,Python类中没有私有方法,但惯例是在
\u my\u private\u方法
中使用前导的
\u
将其标记为私有


我同意答案可能是“不,您必须有4K LOC文件。”

只有在
-export
属性中指定的功能对其他模块可见,即“公共”功能。所有其他功能都是私有的。如果只指定了
-compile(export_all)
,则模块中的所有函数在外部可见。不建议使用
-compile(export_all)

最接近约定的是使用edoc标记,如
@private
@hidden

发件人:

@隐藏

标记该函数,使其不会出现在 文档(即使生成了“私有”文档)。有用的 对于调试/测试功能等,内容可用作注释; 它被EDoc忽略了

@private

将功能标记为私有(即,不是公共的一部分 接口),使其不会出现在正常文档中。 (如果生成了“专用”文档,则该函数将 包括。)仅对导出的函数有用,例如 产卵。(非导出函数始终是“私有的”。)内容可以 用作评论;它被EDoc忽略了


我不知道Erlang有任何现有的约定,但是为什么不采用Python约定呢?假设“库私有”函数的前缀是下划线。要使函数名正常工作,您需要使用单引号引用函数名:

-module(bar).

-export(['_my_private_function'/0]).

'_my_private_function'() ->
    foo.
然后,您可以将其称为:

> bar:'_my_private_function'().
foo
对我来说,这清楚地表明,除非我知道自己在做什么,否则我不应该调用该函数。(甚至可能不会)

请注意,这个答案最初是对@Legossia答案的评论

目前不支持不同方法的不同可见性

如果您想这样称呼它,当前的约定是拥有一个(或多个)导出库/应用程序的公共API的“facade”
my_lib.erl
模块。调用库的任何内部模块都是在玩火,应该避免(调用它们的风险由您自己承担)

BEAM VM中有一些非常好的特性,它们依赖于能够从任何模块调用导出的函数,例如

  • 回调(funs/anonymousfuns),MFA,:调用代码不需要知道库的任何信息,只需要调用它
  • 行为,例如需要上一点才能工作
  • 热重新加载:您可以在不停止VM的情况下升级任何模块的字节码。VM内的代码服务器为任何模块维护最多两个字节码版本,将外部调用(使用
    模块的调用:
    )重定向到最新版本,将内部调用重定向到当前版本。这就是为什么您可能会在长时间运行的服务器中看到一些
    ?模块:
    调用,以便能够升级代码
  • 您可以争辩说,这些点可以使用更细粒度的面向梁的可见性级别,没错。但我不认为它能解决facade模块无法解决的任何问题,而且它会使VM/代码的其他部分变得非常复杂

    奖金

    类似的情况也适用于和类型,记录仅在编译时存在,不透明类型仅在透析器时存在。没有任何东西可以阻止您访问它们的内部结构,但如果您这样做,您只会发现问题:

    • 在记录中插入一个新字段,突然,所有的
      {record\u name,…}=
      都中断了
    • 如果您使用的库返回一个
      不透明的adt()
      ,那么您知道它是一个列表,并且可以这样使用。库被升级为包含列表的大小,因此现在
      opaque\u adt()
      是一个
      tuple()
      ,混乱随之而来

    没错,我想要的是“我的库私有”的概念——我希望使用库中其他模块的函数,而不向库消费者公开它们。例如,Java和(我认为)Go具有包级别的隐私。我很确定在Erlang中没有这样做的方法,但至少有一个约定吗?我的图书馆是私人图书馆。呃??啊……那是不可能的。唯一的方法是使用一个模块来实现所有功能。据我所知,“私人图书馆”没有惯例。对于库中的多个模块使用的函数,我喜欢使用<代码> MyLabyLo.UIL.Erg/>代码>代码> MyLoo.Erl < /> >公共API(我相信这是一个约定)和 MyLabyLogi>….Erl 库中的其他模块。通常的约定(如果你认为它是惯例)是有一个“外观”模块,
    my_lib.erl
    仅导出库的公共接口。调用库中的任何其他方法都是在玩火(但这些方法需要可以从任何其他回调、行为、代码重新加载的代码中访问…)@JoséM我认为您应该基于此评论创建一个答案,这是这里唯一正确的答案。