18 · Módulos
Módulos inline e visibilidade granular
Módulos declarados dentro do arquivo, `use ... as`, e modificadores `pub(mod)` / `pub(crate)`.
Nesta página
Além de módulos em arquivos separados, Zolo permite declarar um módulo
inline dentro do próprio arquivo com mod nome { ... }. Isso é útil para
agrupar funções relacionadas sem criar um arquivo extra.
O use ... as nome (renomeação) cria um alias local — conveniente quando o
nome original é longo ou colide com outro nome no escopo. E os modificadores de
visibilidade pub(mod) e pub(crate) permitem controle mais fino do que o
simples pub:
pub(mod)— visível para irmãos dentro do mesmo módulo inline, mas invisível fora dele.pub(crate)— visível para todo o crate (equivale apubhoje, mas o parser preserva a informação para fases futuras do compilador).
mod arith { ... } é declarado inline; use std::math::{abs as absolute, sign} renomeia durante a importação; pub(mod) secret_factor é usável por
triple (mesmo módulo) mas não pelo código externo.
// Feature: inline `mod foo { ... }`, `use ... as ...` rename, granular
// visibility (private, `pub`, `pub(crate)`, `pub(super)`, `pub(in ...)`,
// `pub(mod)`) and origin-preserving re-exports.
// See `specs/mod-namespace-innovations.html` (cherry-picks C1, C4).
use std::math::{abs as absolute, sign}
// Inline module — declared inside this file, not loaded from disk.
mod arith {
// No modifier: private to canonical module `crate::arith`.
fn private_bias() -> int { 1 }
pub fn add(a: int, b: int) -> int { a + b + private_bias() - 1 }
pub fn mul(a: int, b: int) -> int { a * b }
// pub(mod) keeps the item visible to siblings inside `arith` but
// hidden to the outside file.
pub(mod) fn secret_factor() -> int { 3 }
// pub(crate) crosses module boundaries only inside this crate. The
// resolver, VM/AOT lowerers and editor all use the same canonical region.
pub(crate) fn triple(x: int) -> int { x * secret_factor() }
// The canonical identities are `crate::arith::scoped` and
// `crate::arith::origin`; the local names below are only aliases.
mod scoped {
pub(super) fn parent_only() -> int { 4 }
pub(in crate::arith) fn arith_only() -> int { 5 }
}
pub fn scoped_total() -> int {
scoped.parent_only() + scoped.arith_only()
}
mod origin {
pub(crate) fn crate_value() -> int { 6 }
pub fn public_value() -> int { 7 }
}
// Plain `pub use` cannot widen `crate_value`: the alias remains crate-only
// because the re-export retains and intersects the declaration's origin.
pub use origin::{crate_value as via_facade, public_value}
}
// Bring two items in with renames; the alias becomes the local name.
fn main() {
print("arith.add(2,3) = {arith.add(2, 3)}") // 5
print("arith.mul(2,3) = {arith.mul(2, 3)}") // 6
print("arith.triple(4) = {arith.triple(4)}") // 12 (uses secret_factor)
print("arith.scoped_total() = {arith.scoped_total()}") // 9
print("arith.via_facade() = {arith.via_facade()}") // 6 (crate-only)
print("arith.public_value() = {arith.public_value()}") // 7 (public)
print("absolute(-7) = {absolute(-7)}") // 7
print("sign(-9) = {sign(-9)}") // -1
}
Desafio
Tente chamar arith.secret_factor() a partir de main. O que o compilador
responde? Agora mude pub(mod) para pub e veja a diferença.
Veja também