erg/doc/JA/syntax/26_module.md
2023-06-07 00:27:19 +09:00

131 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# モジュール
[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/syntax/26_module.md%26commit_hash%3Dc8932f8fd75cc86f67421bb6b160fffaf7acdd94)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/26_module.md&commit_hash=c8932f8fd75cc86f67421bb6b160fffaf7acdd94)
Ergでは、ファイル自体を1つのレコードとみなすことができます[<sup id="f1">1</sup>](#1)。これをモジュールと呼びます。
```python,checker_ignore
# foo.er
.i = 1
```
```python
# fooモジュールを定義するのはこのレコードを定義するのと構造的には同じ
foo = {.i = 1}
```
```python,checker_ignore
# bar.er
foo = import "foo"
print! foo # <module 'foo'>
assert foo.i == 1
```
モジュール型は分解代入が可能です。
```python
{sin; cos} = import "math"
```
## モジュールの可視性
ファイルだけでなく、ディレクトリもモジュールとなりえます。
ただしデフォルトでErgはディレクトリをErgモジュールとしては認識しません。認識させるには、`__init__.er`という名前のファイルを作成します。
`__init__.er`はPythonの`__init__.py`と同じようなものです。
```console
└─┬ bar
└─ __init__.er
```
これで、`bar`ディレクトリはモジュールとして認識されます。`bar`内にあるファイルが`__init__.er`だけならばあまりディレクトリ構造にする意味はありませんが、複数のモジュールを束ねて一つのモジュールとしたい場合は便利です。すなわち、このような場合です。
```console
└─┬ bar
├─ __init__.er
├─ baz.er
└─┬ qux
└─ __init__.er
```
```python
# bar/__init__.er
.baz = import "./baz"
.qux = import "./qux"
```
`bar`ディレクトリの外側からは以下のようにして使用できます。
```python
bar = import "bar"
bar.baz.p!()
bar.qux.p!()
```
`__init__.er`は単にディレクトリをモジュールとして機能させるだけのマーカーではなく、モジュールの可視性を制御する役割も持ちます。
Pythonとは違い、Ergのモジュールはデフォルトではインポートできないようになっています。
```python
# __init__.er
# `./`はカレントディレクトリを指す。なくても良い
.baz = import "./baz"
qux = import "./qux"
.f x =
.baz.f ...
.g x =
qux.f ...
```
外から`bar`モジュールをインポートしたとき、`baz`モジュールはアクセス可能ですが、`qux`モジュールはアクセス不可能になります。
## モジュールの循環参照
Ergでは、モジュール間の循環的な依存関係を定義することができます。
```python
# foo.er
bar = import "bar"
print! bar.g 1
.f x = x
```
```python
# bar.er
foo = import "foo"
print! foo.f 1
.g x = x
```
しかし、手続き呼び出しによって作られた変数は、循環参照モジュールで定義することはできません。
これは、Ergが依存関係に従って定義の順番を並べ替えるからです。
```python,compile_fail
# foo.er
bar = import "bar"
print! bar.x
.x = g!(1) # ModuleError: 手続き呼び出しで作られた変数は、循環参照モジュールで定義できない
```
```python
# bar.er
foo = import "foo"
print! foo.x
.x = 0
```
また、エントリポイントであるErgモジュールすなわち `__name__ == "__main__"` であるモジュール)は循環参照の対象になることはできません。
---
<span id="1" style="font-size:x-small"><sup>1</sup> モジュールとレコードの間に直接の部分型関係はないが、形式的にはモジュールがレコードの部分集合である。レコード内では属性の定義のみが行えるが、モジュール内ではあらゆる可能な式を置ける。[](#f1) </span>
<p align='center'>
<a href='./25_closure.md'>Previous</a> | <a href='./27_object_system.md'>Next</a>
</p>