Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

モジュールの宣言

💡 お知らせ: このドキュメントは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 Museumsrc/Museum.flix
pub mod Museum.Entrancesrc/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 という名前にすることはできません。この名前は、プログラムのエントリポイント用に予約されています。