Mozart/Oz について話します

# はじめに

この記事は、[Sansan Advent Calendar 2017](https://adventar.org/calendars/2530) の [16 日目](https://adventar.org/calendars/2530#list-2017-12-16)として書かれたものです。去年は [11 日目の記事](https://qiita.com/mshioda/items/0356659738708d2c936c)として Ada を取り上げました。今年は Mozart/Oz です。


# Mozart/Oz とは？

Mozart/Oz、それは Mozart なのか Oz なのか、あるいはサリエリ[^salieri]に毒殺されたモーツァルトが怨みの底から蘇り、オズ[^wizard_oz]として世界を支配しようとする物語なのか、わたしも調べてみるまではナゾにつつまれたコトバだなと思っていました。しかし調べてみると、実はこれはプログラミング言語の名前なのでした。どうも Oz というのが言語の仕様を指し、Mozart がその実装の名前なのだということだそうです。


# なぜ Mozart/Oz なのか？

なんでも、いま原宿の女子高生の間で大人気だという『コンピュータプログラミングの概念・技法・モデル』という本[^gaudi_book]のなかで、プログラミング言語のパラダイムを紹介するのにつかっているのが、Mozart/Oz なのだそうです。

ここで言っているパラダイムというのは、たとえばオブジェクト指向だとか、関数型プログラミングといった、その言語が戦略的にそなえた構造的な特性のことです。Mozart/Oz は「マルチパラダイム言語」を謳っている言語なので、さまざまなパラダイムが組み込まれています。ですので、プログラミングパラダイムをテーマとした教科書で扱うには都合がよいのかもしれません。

もちろん、C 言語でもオブジェクト指向のようなプログラムが書けるというように、言語にあらかじめ盛り込まれた概念を超えて、パラダイムを表現するということは不可能ではないでしょう。しかし、言語にあらかじめ盛り込まれているならば、そのパラダイムはきっと簡潔にわかりやすく表現できるでしょうし、そのコードを動かしてみれば、そのパラダイムの理想の動き（のひとつ）がどういうものなのか把握しやすいのではないかと思います。ですから、よく設計されたマルチパラダイム言語の言語仕様に触れることは、それぞれのパラダイムを理解することにつながるのではないかと期待できるわけです。



## 残念なお知らせ

Mozart はオープンソースで[公開](http://mozart.github.io/)されていますが、2017年年末現在、どう見ても開発は止まっているようです。[2013 年に書かれた Wiki ページ](https://github.com/mozart/mozart2/wiki/Roadmap)では Mozart 2.0.0 alpha 1 が「very soon!」（間近！）であり、Mozart 2.0.0 stable が「in a few months」（数ヶ月以内）とアナウンスされていますが、2017 年年末現在でも入手できるのは [beta.0 と呼ばれる版のまま](https://github.com/mozart/mozart2#pre-generated-source-tree)です。

Mozart は [1.x.x 系](https://github.com/mozart/mozart)と [2.x.x 系](https://github.com/mozart/mozart2)の 2 つがあり、入手しようとすると基本的に 2.x.x 系へとナビゲーションされるようになっています。しかし 2.x.x 系は beta のままです。しかも、わたしは Arch Linux[^arch_linux] に 2.0.0 beta.0 をインストールしてみたのですが、少なくとも README に書かれた手順では標準ライブラリのいくつかはなぜかインストールされません。これはバグなのか beta の仕様なのかは不明ですが、Mozart に実装されているといわれているすべての機能がつかいたい場合には 1.x.x 系を利用するほうが無難である可能性があります。この記事も、1.4.x を前提に書かれています。



# インストール

前項で書いたとおり、ふつうは 2.x.x 系をインストールするようにナビゲートされると思います。2.x.x 系の場合注意する点は Java のバージョンです。README にはバージョン 1.6.0 以上の Java が必要とだけ書いてありますが、Java 9 ではインストールでエラーになるだろうと思います。わたしは 2.x.x も入れましたが、そのときは Java 7 を使いました。Arch Linux は AUR[^aur] から複数の OpenJDK を自由に入れられるのでこういうときに便利です。

ただ、この記事は 1.x.x 系をつかうことが前提になっています。2017 年現在、1.4.99 が最新です。1.4.x の場合、Ubuntu か Debian にインストールするのが都合がよさそうです[^install]。わたしは VirtualBox に Ubuntu 16.4 をインストールしてそこに入れることにしました。

基本的には README に書かれた手順どおりにインストールすればよいのですが、libgmp-dev は i386 ではないものが必要になります。また、分散プログラミングを試す場合は、リモートホストへのアクセスに ssh をつかいたくなると思います。ですので、ホームディレクトリ配下にインストールすると若干ですがやることが増えそうです。つぎのように手順を変更してもよいかもしれません。

```console
$ sudo apt-get install emacs flex bison tk-dev build-essential g++=multilib zlib1g-dev:i386 libgmp-dev git
$ mkdir ~/works && cd ~/works
$ git clone git://github.com/mozart/mozart.git
$ cd mozart
$ ./configure --prefix=/usr/local/share --disable-contrib-gdbm --enable-modules-static
$ make
$ sudo make install
$ for path in /usr/local/share/mozart/bin/* ; do sudo ln -s ${path} ${path/share\/mozart\//}; done
```

なお、Mozart には OPI（_Oz Programing Interface_）というものがあります。これは Emacs[^emacs] を利用した Mozart の開発環境なのですが、GUI 版 Emacs のマルチウィンドウが前提になっているので、インストールする OS は GUI がつかえるようになっているほうが便利です。もっとも、必須というわけではありません。



## Hello world

もし OPI をつかわずに、ふつうのプログラミング言語のように自由なエディタでコードを書き、コンパイルしたいと望んでいるなら、Hello world をはじめるには [Mozart のドキュメント](http://mozart.github.io/mozart-v1/doc-1.4.0/)を探すより [The Hello World Collection](https://helloworldcollection.github.io/) に掲載された[コード](https://helloworldcollection.github.io/#Oz)を見るのが手っ取り早いでしょう。説明の便宜も含めてここにコードを引用します。

```oz
% Hello World in Oz

functor
import
   System
   Application
define
   {System.showInfo "Hello World!"}
   {Application.exit 0}
end
```

コンパイルするには次のようにします。

```console
$ ozc -x helloworld.oz
```

実行ファイルはそのまま実行できると思いますが、Mozart 2 ではエラーになるかもしれません。その場合はつぎのようにすれば実行できるかもしれません。

```console
$ ozengine helloworld
```

OPI をつかわない Hello world のプログラムはそれなりに長いものになりました。しかし、OPI をつかえばもっとお手軽になります。まず `oz` コマンドで OPI を起動してみましょう。

```console
$ oz &
```

たちあがった Emacs には 2 つのバッファが表示されています。ひとつは `Oz` というバッファです。`*scratch*`[^scratch_buffer] バッファのように、こちらでいろいろコードを書いて試せます。もうひとつは `*Oz Compiler*` というバッファで、こちらにはコンパイルのログが表示されます。

![figure-1.png](https://qiita-image-store.s3.amazonaws.com/0/103414/80bc31d5-bf7d-6fbb-aefa-3aa4ec41ea9a.png)

さて、`Oz` バッファにつぎのように書いて、`C-. C-b`[^emacs_command] とタイプしてみましょう。

```oz
{Show 'Hello World!'}
```

すると `*Oz Compiler*` バッファのほうにログとしてコードがそのまま表示され、つづいて `accepted` と出たと思います。そうなっていれば成功です。`C-. e` をタイプして `*Oz Emulator*` バッファに表示を切り替えて出力結果を確認してみましょう。なお、もとの `*Oz Compiler*` バッファに戻すには `C-. c` とタイプします。

![figure-2.png](https://qiita-image-store.s3.amazonaws.com/0/103414/b5a7b965-0673-587c-74e0-c163981bf203.png)


なお、ここでは公式チュートリアルにならって `{Show ...}` というふうにコードを書きましたが、これは `{System.show ...}` と書いたのと同じ意味です[^browser_command]。最初の Hello world サンプルでは `show` ではなく `showInfo` をつかっていましたから、完全に対応させるなら次のように書くことになります。これももちろん先ほどと同様の操作で実行することができます。

```oz
{System.showInfo "Hello World!"}
```

さて、OPI の例としてはよりお手軽な Oz Browser についても触れておくべきでしょう。これは GUI 版の OPI でなければつかえないと思いますが、便利なので紹介します。`Oz` バッファのコードをつぎのように書き換えて `C-. C-b` を実行してみてください。

```oz
{Browse 'Hello World'}
```

Oz Browser が別フレームで現れ、そこに出力結果が表示されたはずです。

![figure-3.png](https://qiita-image-store.s3.amazonaws.com/0/103414/b6f39cf5-8da5-746a-50f0-a5118fd7d44b.png)

さらに詳しい情報については Mozart/Oz のチュートリアル[^tutorial]を参照してみてください。



## その他コード例

Mozart/Oz の英文のドキュメントにはさまざまなコード例が書かれていますが、全部読むのには骨が折れます。ざっと見渡して試してみるには、[Wikipedia](https://en.wikipedia.org/wiki/Oz_(programming_language)) くらいの簡単な例がよいかもしれません。いくつか見てみましょう。

### 関数

```oz
declare
fun {Fact N}
   if N =< 0 then 1 else N*{Fact N-1} end
end

X = {Fact 10}
{Show X}  % => 3628800
```

OPI でのコード例です。Wikipedia の例はコード片のようなものも多いようで、そのままペースとして試そうとしても動かないことがあるかもしれません。適宜 `declare` などを書き足して文法に適合させる必要がありますので、慣れないうちは注意が必要になります。

上記の例はいわゆる階乗（_Factorial_）の例です。Oz の文法をしらないとしてもプログラムの内容は見当がつくと思います。なお、Oz では識別子は大文字で始める必要があります。変数名が定数名のように大文字なのはそのためです。C 言語流の記法なら `fact(n)` のようになるところが `{Fact N}` のようにカッコの囲み範囲が Lisp 流（？）になっているのも特徴的かもしれません。

なお、コードの記法としては下記のように改行やスペースをつけても問題ありませんが、引数の区切りもスペースなので、演算子などはつなげて書いてしまったほうがわかりよいのかもしれません。コード例ではたいがいそうなっています。

```oz
declare
fun {Fact N}
   if N =< 0 then
      1
   else
      N * {Fact N - 1}
   end
end
```

### パターンマッチ

Oz には `case` をつかったパターンマッチがあるのですが、表記方法はちょっと独特な感じがします。

```oz
declare
fun {SumList List}
   case List of nil then 0
   [] H|T then H+{SumList T}
   end
end

X = {SumList [1 2 3 4 5]}
{Show X}  % => 15
```

文法はつぎのようになっているそうです。`E` の値が `Pattern_1` に合致すれば `S1` が実行され、`Pattern_2` なら `S2`、というふうになります。

```
case E of Pattern_1 then S1
[] Pattern_2 then S2
[] ...
else S
end
```

2 つめ以降のパターンをかく場合には `[]` をつけてつなぐわけですね。この `[]` という表記へのとまどいと、それに続く `H|T` がリスト（配列）を表す[^oz_list]ことがわかれば、あとはなんということもないと思います。念のため、上記のコードをなるべくそのまま Ruby で書いてみましょう。おそらく、つぎのようになる感じでしょうか。

```ruby
def sum_list(list)
  if list.first.nil?
    0
  elsif list.size >= 2
    list.first + sum_list(list[1..-1])
  end
end

x = sum_list([1, 2, 3, 4, 5, nil])
puts x
```

再帰呼び出しを伴っているので、Ruby で書いても若干わかりにくさはあるかもしれません。もちろん Ruby 本来の書き方ならもっと簡潔になるわけですけれども。

```ruby
puts [1, 2, 3, 4, 5].inject(&:+)
```

### データフロー

ここで言っているデータフローというのは、値に束縛されていない変数があると処理を行わずに束縛されるのを待つというものだそうです。要するに値がわからない変数があれば値が入るまで待つということでしょう。

Wikipedia にはちょっと興味深いコード例があります。すこしだけ数値を調整して試してみましょう。

```oz
declare
fun {Ints N Max}
   if N == Max then nil
   else
      {Delay 1000}
      N|{Ints N+1 Max}
   end
end

fun {Sum S Stream}
   case Stream
   of nil then S
   [] H|T then S|{Sum H+S T}
   end
end

local X Y in
   thread X = {Ints 0 10} end
   thread Y = {Sum 0 X} end
   {Browse Y}
end
```

最後のほうの `thread X = {Ints 0 1000} end` のところの数値が Wikipedia では `1000` ですが `10` に変更しています。これは `Delay` によってスリープするようになっているので、時間がかかるからです（`C-. h` で Halt してしまってもいいのですが）。

実行してみると Oz Browser に `Y` のリストが表示されだします。

![video-1.gif](https://qiita-image-store.s3.amazonaws.com/0/103414/4d14ea40-de8a-eef4-2643-48196288db87.gif)

最初は何もないリストに徐々に値が入っていきます。これ、どういうしくみなのでしょうか？

最初の関数 `Ints` は単に 0 から 10 までのリストをつくる関数です。ただし、スリープしながらすこしずつリストを伸ばしていきます。2 番目の関数 `Sum` は、要するに出力結果のような漸化式的な数列をつくっています。

最後に 2 つの `thread` をつくっていますが、`X` の値が追加されると `Y` のほうの計算も追加された分だけ続行され、Oz Browser にそれが表示されるというしくみのようです。

Mozart の `thread` はコストが低いそうですから、試みにもうひとつ足してみましょうか。

```oz
declare
fun {Ints N Max}
   if N == Max then nil
   else
      {Delay 1000}
      N|{Ints N+1 Max}
   end
end

fun {Sum S Stream}
   case Stream
   of nil then S
   [] H|T then S|{Sum H+S T}
   end
end

fun {Fact S Stream}
   case Stream
   of nil then S
   [] H|T then S|{Fact H*(S+1) T}
   end
end

local X Y Z in
   thread X = {Ints 0 10} end
   thread Y = {Sum 0 X} end
   thread Z = {Fact 0 X} end
   {Browse Y}
   {Browse Z}
end
```

これで `X` が増えるたびに `Y` と `Z` の計算が続行されるということになります。

![video-2.gif](https://qiita-image-store.s3.amazonaws.com/0/103414/44fa439e-28d1-cd9a-d053-570aae8717d1.gif)

このように、複数の `thread` をつかって協調的に処理をすすめることもできるわけですね。

# おわりに

Mozart に組み込まれた機能について簡単に紹介してみました。しかし、ここで紹介できたのはほんの少しです。ほかにも、たとえば Oz らしい分散プログラムについてなども紹介してみたかったのですが、長くなってきてしまったのでここで筆を擱くことにします。

　　* * *

さて、ここでちょっと歴史的なことに視線をなげてみましょう。代表的な言語があらわれて以来の、われわれの環境の変化を振り返ってみるのです。すると、マルチコア、Cloud、ビッグデータ、機械学習、などなどけっこう大きく進化しているのではないでしょうか。そうした進化によりよく対応したパラダイムというものは、もしかしたらまだまだ言語に盛り込む余地があるのかもしれません。もしそうしたものが盛り込まれるなら、プログラミングはいっそう魅惑的な「魔術」にちかくなっていくのではないでしょうか。それは見方によれば Oz のような名前をつけるのにふさわしいようなことかもしれません。その実際の使い手の正体が平凡な人であるかもしれないこともふくめて。

[^salieri]: アントニオ・サリエリ Antonio Salieri（1750 - 1825）。元ネタは言わずと知れた映画『アマデウス』（1984年）。
[^wizard_oz]: ライマン・フランク・ボーム作『オズの魔法使い』に出てくる魔法使いを指している。そんな話じゃなかったけ？
[^gaudi_book]: ピーター・ヴァン・ロイ、セイフ・ハリディ著。原題 “_Concepts, Techniques, and Models of Computer Programming_” [翔泳社から日本語訳](http://www.shoeisha.co.jp/book/detail/9784798113463)が出ている。
[^arch_linux]: 本家のページは[こちら](https://www.archlinux.org/)。[日本語ページ](https://www.archlinux.jp/)もある。
[^aur]: _Arch User Repository_ のこと。https://aur.archilinux.org/
[^install]: README には Arch Linux のインストール手順があり、そちらのほうが圧倒的に簡単そうだが、手順で書かれている AUR パッケージはすでに存在していない。別の Mozart パッケージもあるがインストールできないようだ（Mozart 2 のパッケージはインストールできると思うが）。
[^emacs]: GNU Emacs https://www.gnu.org/software/emacs/
[^scratch_buffer]: 簡単にいうと、お手軽に Emacs Lisp が動かせるようになっているバッファ。
[^emacs_command]: Emacs のコマンド表記では `C-` で Control キーを押すことを意味する。 したがって `C-. C-b` は Control キーを押しながら「.」キーを押し、Control キーは押したまま「b」キーを押すことを意味する。 `C-. c` のように、2 回目のキータイプでは Control キーを離すということもある。
[^browser_command]: 対応表が[こちら](http://mozart.github.io/mozart-v1/doc-1.4.0/opi/node4.html#section.mozart)にある。
[^tutorial]: [こちら](http://mozart.github.io/mozart-v1/doc-1.4.0/tutorial/)が本家。日本語に[訳して](e-p-i.github.co/tutorial_of_oz/)くださったかたもいるようだ。
[^oz_list]: Oz のリストはいくつかの表記方法がある。`1|2|3|nil` のように書くこともできるし、`[1 2 3]` のようにも書ける。さらには `'|'(1 '|'(2 '|'(3 nil)))` のように書くこともできる。最後の表記が表しているとおり、基本的に Oz のリストは Lisp のようにペアでできているらしい。パターンマッチの `H|T` はおそらく Head と Tail の意味で、このときの T は先頭要素以外のすべての要素を指す。