elixirでQuineを実装する

## quineとは

quineとは「自分自身の文字列を出力するプログラム」のことです。
[wiki](https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AF%E3%82%A4%E3%83%B3_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0) "Quine")にはいくつかの言語で実装されたquineのサンプルがあります。

この記事ではelixirでQuineを実装しようと思います。

## quineの実装

[あなたの知らない超絶技巧プログラミングの世界](https://www.amazon.co.jp/%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84%E8%B6%85%E7%B5%B6%E6%8A%80%E5%B7%A7%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AE%E4%B8%96%E7%95%8C-%E9%81%A0%E8%97%A4-%E4%BE%91%E4%BB%8B/dp/4774176435 "あなたの知らない超絶技巧プログラミングの世界") という本にQuineの基本的な書き方が載っていました。

Quineの基本的な書き方を引用します。

> (1) 元のプログラム文字列の種となる文字列sを用意する。
> (2) s自身を使ってsの中の一部を適切に書き換え、元のプログラム文字列を再構築する
> (3) 出力する

(2)がややこしいので、(1)と(3)のみを実装したものから始めます。

本ではrubyで説明されていました。

```ruby
s = "..."; print s
```

elixirもここから実装を始めてみます。
```elixir
s="...";s|>IO.puts
```
ここから(2)の部分を追加していきます。
まずは「…」に自分自身を埋め込みます。
```elixir
s="s=\"...\";s|>IO.puts";s|>IO.puts
```
"(ダブルクォテーション）はエスケープしています。

```elixir
iex> s="s=\"...\";s|>IO.puts";s|>IO.puts
s="...";s|>IO.puts
:ok
```

このままでは、変数sしか出力できないので、「…」をsで置換します。
rubyではsubを使用していました。
elixirではString.replaceを使用します。
```elixir
s="s=\"...\";s|>IO.puts";String.replace(s,"...",s,global: false)|>IO.puts
```

```elixir:実行結果
iex> s="s=\"...\";s|>IO.puts";String.replace(s,"...",s,global: false)|>IO.puts
s="s="...";s|>IO.puts";s|>IO.puts
:ok
```
String.replaceを追加したので、変数sも変更します。
```elixir
s="s=\"...\";String.replace(s,\"...\",s,global: false)|>IO.puts";String.replace(s,"...",s,global: false)|>IO.puts
```

```elixir:実行結果
iex> s="s=\"...\";String.replace(s,\"...\",s,global: false)|>IO.puts";String.replace(s,"...",s,global: false)|>IO.puts
s="s="...";String.replace(s,"...",s,global: false)|>IO.puts";String.replace(s,"...",s,global: false)|>IO.puts
:ok
```

ほぼ一致しましたが、`"s=\"...\"`の部分が`"s="..."`になっています。

rubyでも同様の問題があり、置換前にdumpを使って解消していました。
elixirではinspectを使用してみます。（変数sも調整します）
```elixir
s="s=\"...\";String.replace(s,\"...\",inspect(s),global: false)|>IO.puts";String.replace(s,"...",inspect(s),global: false)|>IO.puts
```

```elixir:実行結果
iex> s="s=\"...\";String.replace(s,\"...\",inspect(s),global: false)|>IO.puts";String.replace(s,"...",inspect(s),global: false)|>IO.puts
s=""s=\"...\";String.replace(s,\"...\",inspect(s),global: false)|>IO.puts"";String.replace(s,"...",inspect(s),global: false)|>IO.puts
:ok
```
rubyではここで解決していました。
がelixirだと`s="s=\"`の部分が`s=""s=\"`になっています。

`String.replace(\"\", \")`を追加すればいいのですが、このまま追加すると変数sの調整ができなくなります。
そこでASCIIコードを利用して、`String.replace(<<34, 34>>, <<34>>)`を追加します。

```elixir
s="s=\"...\";String.replace(s,\"...\",inspect(s),global: false)|>String.replace(<<34, 34>>, <<34>>)|>IO.puts";String.replace(s,"...",inspect(s),global: false)|>String.replace(<<34, 34>>, <<34>>)|>IO.puts
```

```elixir:実行結果
iex> s="s=\"...\";String.replace(s,\"...\",inspect(s),global: false)|>String.replace(<<34, 34>>, <<34>>)|>IO.puts";String.replace(s,"...",inspect(s),global: false)|>String.replace(<<34, 34>>, <<34>>)|>IO.puts
s="s=\"...\";String.replace(s,\"...\",inspect(s),global: false)|>String.replace(<<34, 34>>, <<34>>)|>IO.puts";String.replace(s,"...",inspect(s),global: false)|>String.replace(<<34, 34>>, <<34>>)|>IO.puts
:ok
```

rubyより1つ処理が増えましたが、Quineを実装できました。

## 実行結果の確認

Quineが実装できたどうかを確認します。

quine.exsを作成します。
```elixir:quine.exs
s="s=\"...\";String.replace(s,\"...\",inspect(s),global: false)|>String.replace(<<34, 34>>, <<34>>)|>IO.puts";String.replace(s,"...",inspect(s),global: false)|>String.replace(<<34, 34>>, <<34>>)|>IO.puts
```

出力した結果をファイルに保存し比較します。
```
elixir quine.exs > quine.txt
diff quine.exs quine.txt
```

また出力したquine.txtもelixirとして実行できます。
```
cp quine.txt quine2.exs
elixir quine2.exs
```


## その他のQuine

elixirでQuineの実装例を調べてみました。

http://elixirgolf.com/articles/elixir-quine-self-replicating-program/

いくつか実装例がありますが、これがelixirらしくて好きでした。

```elixir
"fn x->IO.puts~s(\#{inspect x}|>\#{x}) end.()"|>fn x->IO.puts~s(#{inspect x}|>#{x}) end.()
```