モジュールの宣言
💡 お知らせ: このドキュメントはAIによって翻訳されています。表現に違和感がある場合は、原文(英語)を参照するか、翻訳にご協力ください。
すでに見てきたように、モジュールは mod キーワードを使って宣言できます:
mod Museum {
// ... メンバー ...
}
入れ子になったモジュール
モジュールは、他のモジュールの中に入れ子にすることができます:
mod Museum {
mod Entrance {
pub def buyTicket(): Unit \ IO =
println("Museum.Entrance.buyTicket() was called.")
}
mod Restaurant {
pub def buyMeal(): Unit \ IO =
println("Museum.Restaurant.buyMeal() was called.")
}
mod Giftshop {
pub def buyGift(): Unit \ IO =
println("Museum.Giftshop.buyGift() was called.")
}
pub def visit(): Unit \ IO =
Entrance.buyTicket();
Restaurant.buyMeal();
Giftshop.buyGift()
}
ここでは Entrance、Restaurant、Giftshop の各モジュールが Museum モジュールの中に入れ子になっており、visit 関数がそれぞれのモジュールから関数を呼び出しています。
visit は、Museum モジュールの外から呼び出すことができます:
def main(): Unit \ IO =
Museum.visit()
モジュールは、公開(pub)として宣言しない限り、それが宣言されているモジュールに対してプライベートです。したがって、3つの入れ子になったモジュールは visit がそうしているように Museum の内部からは利用できますが、外部からは利用できません。次のように書こうとすると:
def main(): Unit \ IO =
Museum.Entrance.buyTicket()
Flix は次のように報告します:
-- Resolution Error [E2544] -------------------------------------- src/Main.flix
>> Module 'Museum.Entrance' is not accessible from the module ''.
2 | Museum.Entrance.buyTicket()
^^^^^^^^^^^^^^^^^^^^^^^^^
inaccessible module
Tip: Mark the module as 'pub'.
公開モジュール
モジュールを pub mod として公開として宣言すると、どこからでもアクセスできるようになります。公開モジュールは、それ専用のファイルのトップレベルにフルネームで宣言され、ファイルのパスはモジュールの名前と一致していなければなりません:
| モジュール | ファイル |
|---|---|
pub mod Museum | src/Museum.flix |
pub mod Museum.Entrance | src/Museum/Entrance.flix |
例えば、博物館(Museum)の入口(Entrance)を公開することができます。ファイル src/Museum.flix に次のように書きます:
pub mod Museum {
pub def visit(): Unit \ IO =
Entrance.buyTicket()
}
そして、ファイル src/Museum/Entrance.flix に次のように書きます:
pub mod Museum.Entrance {
pub def buyTicket(): Unit \ IO =
println("Museum.Entrance.buyTicket() was called.")
}
ここで Museum.Entrance は、入れ子にした場合と同様に Museum モジュールの中の Entrance モジュールですが、今回は公開されています。buyTicket はどこからでも呼び出すことができます:
def main(): Unit \ IO =
Museum.Entrance.buyTicket()
あるいは、次のようにすることもできます:
use Museum.Entrance.buyTicket;
def main(): Unit \ IO =
buyTicket()
公開モジュールは、他のモジュールの本体の中に入れ子にすることはできません。Museum の本体の中で pub mod Entrance と書くと、Flix は次のように報告します:
-- Name Error [E5544] ------------------------------------------ src/Museum.flix
>> Nested public module: 'Museum.Entrance'.
2 | pub mod Entrance {
^^^^^^^^
nested public module
Explanation: A public module must be declared at the top level of its
own file, not inside another module. For example:
// File Museum/Entrance.flix
pub mod Museum.Entrance { ... }
注意: モジュールの親は宣言されていなければなりません。
Museumモジュールを宣言せずにMuseum.Entranceモジュールを宣言することはできません。
注意: プライベートなモジュールはどのファイルにも宣言でき、また
mod Museum.Vault { ... }のようにフルネームで宣言することもできます。これはMuseumに対してプライベートなモジュールを宣言します。
アクセシビリティ
モジュールとそのメンバーは、デフォルトではプライベートです。pub 修飾子を使うことで、それらを公開にできます。
モジュール A の中で宣言されたモジュールまたはメンバー m は、次のいずれかの場合に別のモジュール B からアクセスできます:
mが公開(pub)として宣言されている。- モジュール
Bが、モジュールA自身である、またはAの中に入れ子になっている。
例えば、次のコードは許可されます:
mod A {
mod B {
pub def g(): Unit \ IO = A.f() // OK
}
def f(): Unit \ IO = println("A.f() was called.")
}
ここで f はモジュール A に対してプライベートです。しかし、B は A の中に入れ子になっているため、B の内部から f にアクセスできます。一方、次のコードは許可されません:
mod A {
mod B {
def g(): Unit \ IO = println("A.B.g() was called.")
}
pub def f(): Unit \ IO = A.B.g() // NOT OK
}
なぜなら、g は B に対してプライベートだからです。
同じ規則が、モジュール自身にも適用されます。例えば、次のコードは許可されます:
mod A {
mod B {
pub def g(): Unit \ IO = println("A.B.g() was called.")
}
mod C {
pub def h(): Unit \ IO = A.B.g() // OK
}
}
ここで B はモジュール A に対してプライベートです。しかし、C は A の中に入れ子になっているため、C の内部から B にアクセスできます。
A.B.g のような修飾名を書く場合、途中のすべてのモジュールがアクセス可能でなければならず、メンバー自身もアクセス可能でなければなりません。
注意:
Aのように他のモジュールの中に入れ子になっていないモジュールは、公開されているかどうかにかかわらず、プロジェクトのすべてのモジュールからアクセスできます。
モジュールの宣言は一度だけ
モジュールの宣言箇所は、ちょうど1つだけです。同じファイルであっても別のファイルであっても、モジュールを宣言した後に、それを再度開いてメンバーを追加することはできません。
例えば、次のように書くと:
mod Museum {
pub def open(): Unit \ IO = println("The museum is open.")
}
mod Museum {
pub def close(): Unit \ IO = println("The museum is closed.")
}
Flix は次のように報告します:
-- Name Error [E5410] -------------------------------------------- src/Main.flix
>> Duplicate module: 'Museum'.
1 | mod Museum {
^^^^^^
first declaration in src/Main.flix
5 | mod Museum {
^^^^^^
duplicate declaration in src/Main.flix
Explanation: A module may have only one declaration site
in the program. Reopening a module — either across files or as multiple
sibling blocks — is not allowed. Combine the declarations into a single
module body.
代わりに、両方の関数を同じモジュールの中で宣言する必要があります。
注意: 標準ライブラリのモジュールも、宣言は一度だけです。したがって、
List、Math、Stringなどの標準ライブラリのモジュールと同じ名前でモジュールを宣言することはできません。
注意: トップレベルのモジュールを
Mainという名前にすることはできません。この名前は、プログラムのエントリポイント用に予約されています。