Elixir 1.8.0が正規リリースされた
Tags: elixir, webdev, tutorial, programming
Published: 2019-01-16 04:44:18

---
title: Elixir 1.8.0が正規リリースされた
published: true
description: Elixir 1.8が正規リリースされました。おもに、基盤となる部分の改善が加えられたということです。リリースノートをもとに、4つの項目についてご説明します。
tags: #elixir, #webdev, #tutorial, #programming
---

Elixir 1.8が正規リリースされました。おもに、基盤となる部分の改善が加えられたということです。本稿は、[リリースノート](https://github.com/elixir-lang/elixir/releases/tag/v1.8.0)(英語)をもとに、つぎの4つの項目についてご説明します。

- カスタム構造検査
- タイムゾーンデータベースへの対応
- コンパイルの高速化とその他のパフォーマンス改善
- 計測・監視機能の改善と$callersの追加


# カスタム構造検査
Elixirの[`Inspect`](https://hexdocs.pm/elixir/Inspect.html)プロトコルの実装が、データを抽出できるようになりました。データ構造を検査するときに、フィールドが簡単にフィルタリングできるのです。ユーザーのデータ構造がプライバシーに関わる情報を含んでいる場合などに使えます。たとえばつぎの構造体で、`:email`や`:encrypted_password`といった個人情報です。[`inspect/2`](https://hexdocs.pm/elixir/Kernel.html#inspect/2)関数で調べると、デフォルトではすべてのフィールドが取り出されます。

```elixir
defmodule User do
  defstruct [:id, :name, :age, :email, :encrypted_password]
end
```

ログやエラーレポートなどに出力したくないデータについては、`Inspect`プロトコルのカスタム実装が定められます。Elixir 1.8ではさらに、`Inspect`プロトコルに[`@derive`](https://hexdocs.pm/elixir/Inspect.html#module-deriving)を加えて、簡単にデータが抽出できるようになりました。オプション`:only`でフィールドを選べば、他は表示されません。

```elixir
defmodule User do
  @derive {Inspect, only: [:id, :name, :age]}
  defstruct [:id, :name, :age, :email, :encrypted_password]
end

inspect(%User{id: 1, name: "Homer", age: 33, address: "742 Evergreen Terrace"})
#=> #User<id: 1, name: "Homer", age: 33, ...>
```

オプションにはもうひとつ、表示しないフィールドを絞る`:except`があります(`@derive {Inspect, except: [...]}`)。



# タイムゾーンデータベースへの対応
Elixir 1.3では日付と時刻を扱うために、つぎの4つのカレンダー型を備えました。

- `Time`
- `Date`
- `NaiveDateTime`(タイムゾーンなし)
- `DateTime`(タイムゾーンあり)

その後のアップデートでカレンダー型には改善が加えられたものの、[`DateTime`](https://hexdocs.pm/elixir/DateTime.html)モジュールがタイムゾーンデータベースに対応するにはいたりませんでした。

Elixir 1.8には新たに[`Calendar.TimeZoneDatabase`](https://hexdocs.pm/elixir/Calendar.TimeZoneDatabase.html)ビヘイビアが加わっています。このビヘイビアで、開発者は独自にタイムゾーンデータベースを取り込めるのです。タイムゾーンのビヘイビアに規約を明示的に定めることで、Elixirの`DateTime API`が拡張できます。たとえば、`DateTime`のタイムゾーンを変えるのが[`DateTime.shift_zone/3`](https://hexdocs.pm/elixir/DateTime.html#shift_zone/3)関数です。Elixirはデフォルトでは、UTCのみを扱う[`Calendar.UTCOnlyTimeZoneDatabase`](https://hexdocs.pm/elixir/Calendar.UTCOnlyTimeZoneDatabase.html)をタイムゾーンデータベースとして備えます。

そのほかカレンダーに関わる改善として、つぎの4つの関数が新しく加わりました。

- [`Date.day_of_year/1`](https://hexdocs.pm/elixir/Date.html#day_of_year/1)
- [`Date.quarter_of_year/1`](https://hexdocs.pm/elixir/Date.html#quarter_of_year/1)
- [`Date.year_of_era/1`](https://hexdocs.pm/elixir/Date.html#year_of_era/1)
- [`Date.day_of_era/1`](https://hexdocs.pm/elixir/Date.html#day_of_era/1)


# コンパイルの高速化とその他のパフォーマンス改善
昨年コンパイラを改善したことにより、Elixir 1.8のコンパイルは平均5%速くなりました。さらに今回、コンパイル時間を縮め、快適な開発ができるための改善を加えています。

つぎの場合に、コンパイラはより効率的なコードを生成します。

- ガードにおける範囲確認(`x in y..z`など)
- 文字リストの内挿(`'foo #{bar} baz'`など)
- [`Record`](https://hexdocs.pm/elixir/Record.html)モジュールのレコード操作

[`EEx`](https://hexdocs.pm/eex/EEx.html)テンプレートには共通の最適化を加え、コードは小さくなり、実行が速まりました。


# 計測・監視機能の改善と$callersの追加
[`Task`](https://hexdocs.pm/elixir/Task.html)モジュールは、軽いプロセスをいくつも生成して同時に処理するためによく用いられます。そして、Elixirが新たなプロセスをつくったとき、その親を示すために付されるのが`$ancestors`キーです。この情報は、計測ツールが複数のプロセス内で起こるイベントの関係を追跡するために使われます。ただ多くの場合、`$ancestors`の情報だけでは足りません。

タスクはスーパーバイザーのもとで開始することが推奨されています。見通しがよくなり、ノードが落ちたときにタスクをどう終わらせるか管理できるからです。そのためには、たとえばつぎのコードのようにタスクを実行するでしょう。タスクはこのコードによりつくられます。けれどこのとき、タスクを直接生成した親はスーパーバイザーになってしまうのです。スーパーバイザーはタスクの`$ancestors`リストに含まれます。けれど、コードとの関係は失われてしまうのです。

```elixir
Task.Supervisor.start_child(MySupervisor, task_specification)
```

Elixir 1.8では、コードとタスクとの関係は、プロセスの辞書から`$callers`キーで追跡できるようになりました。このキーは、`$ancestors`とともに使えます。前掲の`Task.Supervisor`を用いたコードでは、つぎのような関係になるでしょう。

![elixir_v18_001_02.png](https://thepracticaldev.s3.amazonaws.com/i/o1usuov1q7b4h15360su.png)

このとき、ふたつのキー`$ancestors`と`$callers`に加えられるのはつぎのとおりです。

![elixir_v18_001_01.png](https://thepracticaldev.s3.amazonaws.com/i/g1e1vup9n0lpf0bzwom8.png)

スーパーバイザーは使わず、コードから直にタスクをつくると、コードが走っているプロセスは、`$ancestors`と`$callers`の両方のリストに入ります。

この機能により、計測と監視のツールが、システム内で起きたイベントの追跡や関連づけをしやすくなるでしょう。さらに、Ectoサンドボックスのようなツールでも使えるのです。Ectoサンドボックスにより、データベースに対するテストは複数同時にできます。そこで用いられるトランザクションと所有メカニズムには、各プロセスが明示的に割り当てられています。`$callers`がないと、データベースに問い合わせるタスクをつくっても、タスクはどこから呼び出されたのかわからず、どこに接続されているのか知ることができません。すると多くの場合、タスクに依存する機能は同時にテストできないことになります。`$callers`によりこれが簡単にわかり、マシンのパワーをフルに活かしたテストが可能になるのです。

詳しい変更については[リリースノート](https://github.com/elixir-lang/elixir/releases/tag/v1.8.0)(英語)をご参照ください。