在模块(分发?)级别强制执行API边界

我如何构建 Raku 代码,以便某些符号我正在编写的库中是公开的,但不对库的用户公开?(我说“库”是为了避免使用术语“分发”和“模块”,文档有时会以重叠的方式使用它们。但如果我应该使用更精确的术语,请告诉我。)

我了解如何在单个文件中控制隐私。例如,我可能有一个Foo.rakumod包含以下内容的文件:

unit module Foo;

sub private($priv) { #`[do internal stuff] }

our sub public($input) is export { #`[ code that calls &private ] }

使用此设置,&public是我图书馆公共 API 的一部分,但&private不是 - 我可以在 内调用它Foo,但我的用户不能。

如果&private变得足够大以至于我想将其拆分为自己的文件,我该如何保持这种分离?如果我&private进入 . Bar.rakumod,那么我将需要从模块中给它our(即包)范围和exportBar,以便能够useFoo. 但以同样的方式我出口这样&publicFoo会导致我的库的用户能够use Foo和呼叫&private-也就是结局我想避免的。如何维护&private的隐私?

(我通过在 META6.json 文件中将Foo我的分发版provides列为一个模块来研究强制执行隐私。但从文档中,我的理解是,provides默认情况下控制哪些模块包管理器像 zef install 但实际上并不控制代码的隐私。 那是对的吗?)

[编辑:我得到的前几个回复让我怀疑我是否遇到了XY 问题。我以为我问的是“简单的事情应该很容易”类别中的某些内容。我正在解决从 Rust 背景强制执行 API 边界的问题,其中常见的做法是将模块在 crate 中公开(或仅公开给它们的父模块)——这就是 XI 所问的问题。但是,如果有更好/不同的方式来强制 Raku 中的 API 边界,我也会对该解决方案感兴趣(因为这是 YI 真正关心的)]

回答

我需要给它我们的(即包)范围并从 Bar 模块导出它

第一步不是必须的。该export机制也适用于词法范围的subs,这意味着它们仅可用于导入它们的模块。由于没有隐式重新导出,模块用户必须显式使用包含实现细节的模块才能获得它们。(our顺便说一句,就我个人而言,我几乎从不使用模块中的 subs 范围,并且完全依赖于导出。但是,我明白为什么人们也可能决定以完全限定的名称提供它们。)

也可以对内部事物使用导出标签(is export(:INTERNAL), 然后use My::Module::Internals :INTERNAL),以向模块用户提供更强有力的提示,即他们正在使保修无效。归根结底,无论语言提供什么,有足够决心重用内部结构的人都会找到一种方法(即使它是从您的模块复制粘贴)。总的来说,Raku 的设计更侧重于让人们更容易做正确的事情,而不是让他们不可能“错误”的事情,如果他们真的想要的话,因为有时错误的事情仍然比其他选择的错误要少.


回答

Off the bat, there's very little you can't do, as long as you're in control of the meta-object protocol. Anything that's syntactically possible, you could in principle do it using a specific kind of method, or class, declared using that. For instance, you could have a private-class which would be visible only to members of the same namespace (to the level that you would design). There's Metamodel::Trusting which defines, for a particular entity, who it does trust (please bear in mind that this is part of the implementation, not spec, and then subject to change).

一种可扩展性较差的方法是使用trusts. 新的私有模块需要是类,并trusts X为每个访问它的类发出一个。这可能包括属于同一发行版的类……与否,这由您决定。正是上面的 Metamodel 类提供了这个特性,所以直接使用它可能会给你更高级别的控制(使用较低级别的编程)


以上是在模块(分发?)级别强制执行API边界的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>