fluorite-7　日本語チュートリアル　Part 9　オブジェクト


[チュートリアルトップ](https://qiita.com/MirrgieRiana/items/a0906c72ebfb46693ab5)

[←前回](https://qiita.com/MirrgieRiana/items/d4af50233a37e5d84646)　[次回→](https://qiita.com/MirrgieRiana/items/e69d38f6a1f1213f7760)

このパートでは、文字列と値の組であるオブジェクトについて取り扱います。

# レッスン1　オブジェクト

fluorite-7において、**オブジェクト**とは文字列から値を引くことができる辞書です。
何も定義されていない空のオブジェクトを作るには、`{}`と記述します。
この演算子を、**オブジェクト初期化子**と呼びます。

```bash:
$ fl7 '{}'
{}
```

# レッスン2　プロパティの宣言

`{`と`}`の間で「**キー**`:`**値**」と記述することで**プロパティ**を**宣言**できます。

```bash:
$ fl7 '{a: 10}'
{a:10}
```

プロパティは`;`で区切ることで複数宣言できます。
`;`は無駄に大量に並べても、単に無視されます。

```bash:
$ fl7 '{a: 10; b: 200}'
{a:10;b:200}

$ fl7 '{;;;a: 10;;; b: 200;;;}'
{a:10;b:200}
```

キーに識別子を書いた場合はその識別子の名前がキーになりますが、そうでない場合はその式が評価されてキーとなります。

```bash:
$ fl7 '{"#": 10}'
{#:10}

$ fl7 '{"a" & "b": 10}'
{ab:10}

$ fl7 'k: "a"; {(k): 10}'
{a:10}
```

# レッスン3　プロパティへのアクセス

「オブジェクト`.`識別子」もしくは「オブジェクト`[`文字列`]`」でオブジェクトのプロパティにアクセスします。

```bash:
$ fl7 '{a: 10; b: 200}.b'
200

$ fl7 '{a: 10; b: 200}["b"]'
200
```

`[` `]`によるアクセスは文字列であることに気を付けてください。
その場所に識別子を書いたとき、その名前が既に使用済みであれば、その名前が示す値がキーとして使われます。

```bash:
$ fl7 'a: "b"; {a: 10; b: 200}[a]'
200
```

また、「オブジェクト`."`キー`"`」のように書くと、こちらでも文字列による指定ができます。

```bash:
$ fl7 '{ab: 10}.ab'
10

$ fl7 '{ab: 10}."ab"'
10

$ fl7 '{ab: 10}.("a" & "b")'
10
```

存在しないキーにアクセスすると、NULLが返されます。

```bash:
$ fl7 '{a: 10}.b'
NULL
```

# レッスン4　オブジェクトの継承

fluorite-7のオブジェクトは継承することができます。
継承するには、「オブジェクト`{` `}`」と記述します。
継承したオブジェクトに対して`.`でアクセスをすると、親オブジェクトのプロパティも見えるようになります。

```bash:
$ fl7 '{a: 10}{b: 200}.a'
10
```

親オブジェクトと同じ名前のプロパティがあった場合は、子オブジェクトのプロパティが優先されます。

```bash:
$ fl7 '{a: 10}{a: 200}.a'
200
```

一方、`[` `]`によるアクセスは継承を考慮しません。

```bash:
$ fl7 '{a: 10}{b: 200}["a"]'
NULL
```

継承を考慮したプロパティのアクセスを**メンバアクセス**、`.`を**メンバアクセス演算子**と呼びます。

# レッスン5　オブジェクトのストリーマ展開

オブジェクトをストリーマ展開すると、そのオブジェクトのプロパティのストリーマが得られます。
親オブジェクトのプロパティは参照しません。

```bash:
$ fl7 '{a: 10}{b: 200; c: 4}[]'
{key:b;value:200}
{key:c;value:4}
```

# レッスン6　オブジェクトの文字列化

オブジェクトを文字列化すると、継承を無視したプロパティの一覧が得られます。

```bash:
$ fl7 '&{a: 10}{b: 200; c: 4}'
{b:200;c:4}
```

# レッスン7　プロパティのストリーマからのオブジェクト構築

演算子`{[` `]}`は、プロパティのストリーマからオブジェクトを構築します。

```bash:
$ fl7 '{[ {key:A;value:B},{key:C;value:D} ]}'
{A:B;C:D}
```

丁度ストリーマ展開と逆の操作です。

# レッスン8　宣言されたプロパティへの参照

オブジェクト初期化子の中で「識別子`:`」によって定義されたプロパティは、そのオブジェクト初期化子の中から名前で呼べるようになります。

```bash:
$ fl7 '{y: x * 20; x: 3; z: x + y}'
{y:60;x:3;z:63}
```

整形してみましょう。

```perl:
{
  y: x * 20;
  x: 3;
  z: x + y;
}
```

見ての通り、`y`の値は`x`に依存し、`z`の値は`x`と`y`に依存します。
このプロパティは`x`→`y`→`z`の順番でセットしなければなりませんが、実際そのような順番でセットされます。

オブジェクト初期化子がオブジェクトを初期化する過程において、この依存関係は循環してはなりません。
例えば次のようなものは循環が起こります。

```bash:
$ fl7 '{x: x}'
```

`x`を初期化するには`x`が必要ですが、その`x`を初期化するために`x`が必要です。

----

> オブジェクト初期化子がオブジェクトを初期化する過程において、この依存関係は循環してはなりません。

しかし、「オブジェクトを初期化する過程」でなければ循環してもかまいません。

```bash:
$ fl7 '{f: () -> f}'
{f:[FluoriteFunction]}
```

これは評価すると関数`f`が返ってくる関数`f`が定義されたオブジェクトです。
このように名前の参照が遅延される場合であれば、自由に名前を利用することができます。

# レッスン9　プロパティ初期化における代入と即席代入

オブジェクト初期化子の中でプロパティが名前で直接呼べるようになることは、良いことばかりではありません。
既存の変数と同名のプロパティを作る状況はよくあることです。

そういう状況の為に、**代入**というプロパティ初期化の方法があります。
代入によるプロパティ初期化を行うには、`:`の代わりに`=`を使用します。

```bash:
$ fl7 'x: 5; {x = x}'
{x:5}
```

`x: x`では循環参照のエラーになっていたものが、`x = x`では正しく`x`というキーに変数`x`の中身がセットされました。

更に、値部分が1個の識別子のみで、キーがその識別子と同じ場合、**即席代入**を使うことができます。
即席代入は、もはや`=`も書かず、単にその識別子を記述するだけです。

```bash:
$ fl7 'x: 5; {x}'
{x:5}

$ fl7 'p: k, v -> {k; v}; p("a"; 50)'
{k:a;v:50}
```

# まとめ

- `{` `}`でオブジェクトを作る。
- `key: value`でプロパティを宣言。
- プロパティは`;`で区切って複数初期化できる。
- `object{}`で継承つきオブジェクトを生成。
- `object.identifier`でメンバアクセス。
- メンバアクセスは継承を考慮する。
- `object[string]`で通常のプロパティアクセス。
- `object[]`でプロパティのストリーマを得る。
- `{[` `]}`でプロパティのストリーマから構築。
- `key = value`はプロパティの代入。
- `identifier`はプロパティの即席代入。
- キーが識別子の宣言は、同じオブジェクト初期化子の中から名前で呼べるようになる。
- オブジェクト初期化時に依存関係が循環するように名前を参照することはできない。

# Part 10

[次回→](https://qiita.com/MirrgieRiana/items/e69d38f6a1f1213f7760)