LoginSignup
10
3

More than 5 years have passed since last update.

演算子の再定義とペアノの算法 -Elixir見習いの実習ー

Last updated at Posted at 2019-01-03

はじめに

「プログラミングElixir」の第20章、20.7に従い演算子の再定義に取り組みました。

これはまちがいなく危険な領域だ

本のp254には予めシステムが用意している演算子を再定義する方法について述べられています。これを使い、加算の+演算子をペアノの算法に置き換えてみます。

ペアノの算法

ペアノの公理系により自然数とその演算が厳密に定義されています。詳細はwikipediaをご覧ください。
https://ja.wikipedia.org/wiki/ペアノの公理

Elixirのリストを自然数として扱います。空リスト [] を0とします。[[]]は1、[[[]]]は2とします。後続数を表すsucc/1と ひとつ前の数を表すprev/1を定義します。そうすると加算は次のadd/2ように定義することができます。


defmodule Peano do
  defmacro a + b do
    quote do
      add(unquote(a),unquote(b))
    end
  end

  def succ(n) do
    [n]
  end

  def prev([n]) do
    n
  end

  def add(a,[]) do a end
  def add(a,b) do
    add(succ(a),prev(b))
  end
end


試してみます。

iex(7)> Peano.add([[[]]],[[]])
[[[[]]]]
iex(8)>


演算子の再定義

ElixirにはLisp並みに柔軟な機構が備わっています。演算子を再定義できてしまいます。+の定義を除外してカーネルをインポートし、独自に再定義した上記のペアノの算法での加算に入れ替えます。驚いたことにモジュールTestのスコープ内では+演算子はペアノの算法の加算として機能します。


defmodule Test do
  import Kernel, except: [+: 2]
  import Peano

  def foo(a,b) do
    a+b
  end
end

iex(9)> Test.foo([[]],[[[]]])
[[[[]]]]
iex(10)>

終わりに

Elixirの柔軟な機能に驚きました。Lispでは演算子を再定義することは容易いことですが、まさかアルゴル系言語のElixirでこんなことができるとは思いませんでした。どういう使い道があるのかはわかりませんが、Elixirの底力を垣間見たような気持ちです。

参考文献

「プログラミングElixir」 笹田耕一、鳥井雪 共訳 Ohmsha

10
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
3