読者です 読者をやめる 読者になる 読者になる

さんぽみち

なにか思いついたときとかに気まぐれに更新されます。

Stateモナドは一度実装すべき

はじめに

そういや Haskell で State モナドの挙動をちゃんと理解してなかったなぁと思ったのでとりあえず別言語で実装してみたらすんなり理解できた話。
チュートリアルを書きたいわけではないので、自分がなぜ理解に苦しんだのかについて焦点を当てたいと思います。

実装

Ruby で書きました。
短いので意味をかみしめながらでも短時間で実装できます。
テストはみんな大好きスタックの実装!
空になった後とか push 直後とか雑だけど目的が実装の理解なので目をつむってください。
State.rb

class State
  def self.unit(v)
    state{|s| next v, s }
  end
  def self.state(&g)
    self.new(g)
  end
  def self.get
    state{|s| next s, s }
  end
  def self.put(s)
    state{|_| next nil, s }
  end
  
  attr_reader :g
  def initialize(g)
    @g = g
  end
  def bind(&f)
    State.state{|s|
      v, ns = @g.call(s)
      f.call(v).g.call(ns)
    }
  end
  def runState(s)
    @g.call(s)
  end

  def >=(f)
    bind(&f)
  end
end

test.rb

require('./State.rb')

def pop
  State.state{|s| next s.last, s[0...s.length - 1] }
end
def push(v)
  State.get.bind{|s| State.put(s << v) }
end

# run
push(1)
  .bind{|_| push(2) }
  .bind{|_| push(3) }
  .bind{|_| push(4) }
  .bind{|_| push(5).bind{|_| pop } }
  .bind{|v| p v; pop }
  .bind{|v| p v; push(10).bind{|_| pop} }
  .bind{|v| p v; pop }
  .bind{|v| p v; pop }
  .bind{|v| p v; pop }
  .bind{|v| p v; pop }
  .bind{|v| p v; pop }
  .runState([])

結果

5
4
10
3
2
1
nil

何がわかりづらかった?

伝搬するのは状態でなく関数であること

このモナドは、バインド関数によって関数を合成しながら引き継いでいきます。
状態を取りまわせるという触れ込みで変な先入観がうまれて理解を妨げていたっぽいです。

与えられる値は前回指定し、値を利用後に次の値を取り出す方法を指定する

do記法で書くと違和感なく使えるけど、理解するためにすべて演算子に落として考えた時にずれているのがややこしいです。

実装した感想

まず、状態から取り出した値をどのように渡すかがわかりやすいです。
なにせ自分で渡してますので。
あとは runState で渡した状態情報が吸いあがって最初の関数から順番に適用されていく感覚がつかめて結構楽しいかも。
この二点が主な収穫で、状態情報と実装が完全に切り離されて参照透過なまま状態情報を共有できていることへの理解が深まりました。

おまけ

>>= 演算子と似てるなーってことで >= 演算子をオーバーライドして bind 関数をラップしてやったけど、これを使ってアロー演算子ラムダ式を定義してバインドしてやると

( pop \
  >=-> v{ p v; pop } \
  >=-> v{ p v; pop } \
  >=-> v{ p v; pop } \
  >=-> v{ p v; pop }
).runState([1,2,3,4])

って書けます。
なんかかっこいい!!

参考

タマニチェンコ様(2014)Stateモナドがわかればモナドがわかる - セカイノカタチ

 bind 関数の実装で参考にさせていただきました。
 技術の話をしながらもユーモアに富んだ楽しい記事を書かれています。
 同ページにリンクのあるIOモナドの図解も、笑いながら理解に輪郭を与えてくれる素敵な記事です。

SQLは怖くない

はじめに

SQLって要するに集合論だと聞いたのに、全然それがわからない!って人向けです。
多くの説明が手続き的に説明されており、前提知識が0の人のみがわかりやすい説明です。
せっかく分野を超えて一般的である集合論が根っこにあり多くの人が身に付けているのに、これを利用した説明がなされないのは効率が悪いと感じております。
また、情報分野の技術あるあるとして、

  1. 数学で概念が定義され名づけられる
  2. 情報で応用する際に別名を名づける
  3. 別名が浸透する
  4. 数学で名づけられた一般的な名前を知らない人ばかりになる
  5. 他分野から来た人が数学の知識を流用できない
  6. 他分野から来た人が、自分の持っていた知識に関連があると気づく
  7. 確認しようとすると、 4. より周りが説明できず、結局知識を流用できない

といった流れがあります。
この循環を断ち切る為にも、SQLを手続き的に理解している人向けでもあります。

RDBの要素

RDB(リレーショナルデータベース)は、情報の意味に関する情報を省くと複数のテーブルと呼ばれる集合を集めただけの物です。
ここへ意味に関する情報を付与するとグラフとしての性質が生まれます。
グラフによって集合を関連付け、関連付けた集合へ演算を行って新しい集合を作るといった使い方になります。
また、このグラフを表現するのに利用されるのがER図と呼ばれる図です。
今回は、テーブルについて考えてみます。

テーブル

テーブルは、タプル(レコードと呼ばれる)を元とした集合です。
レコードの構造と要素を参照する際に用いる添え字(フィールドと呼ばれる)を定義します。
直交した値の関係性を定義することから、このタプルの構造を “リレーション” と呼びます。

レコード

テーブルで定義された構造を持つタプルの値です。
“元” と同義ですが “レコード” と呼ばれます。

フィールド

レコードの要素を参照する為のインデックスを抽象化して文字にしたものです。
“主キー” と呼ばれるものもフィールドの一つです。

主キー

レコードが一意となることを保証するためのメタ的な意味を持ったフィールドです。
一般的には、これをどのテーブルの主キーであるかというメタ情報とともに他のテーブルへ埋め込むことで関係を示します。
この関係のことを “リレーションシップ” と呼びます。

データの加工方法

SQLが力を発揮するのは、データを参照するときです。
ですので戻り値がテーブルとなるSELECT文について書きます。
実行順番等の記述がありますが、実際にその処理が行われているというわけではなく、意味として何を行うかについて書いています。

SELECT文の構造

まずは基本的な要素について大雑把に説明すると、

SELECT
  写像の定義
FROM
  直積を取りたい集合を列挙
WHERE
  部分集合の作り方

となります。
実行する順番に並び替えると、

FROM
  直積を取りたい集合を列挙
WHERE
  部分集合の作り方
SELECT
  写像の定義

となり、

  1. くっつけて
  2. 絞って
  3. 加工する

という手順を行っているのがわかると思います。
SELECTの動作について、厳密には写像をフラットにするという意味もありますが今回は追及しません。

検証

九九の計算から平方数を生み出す2数と計算結果を元とした集合を作っていきます。
ただし、平方数は同じ数を乗じて作られるもののみで、2×8などは含まないとします。
実行環境は、

sqlfiddle.com

こんなのを見つけたのでここでやってみます。

テーブルの定義

元となるテーブルは、

-- row = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
CREATE TABLE row(r INTEGER PRIMARY KEY);
INSERT INTO row VALUES
  (1), (2), (3), (4), (5), (6), (7), (8), (9)
;

-- col = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
CREATE TABLE col(c INTEGER PRIMARY KEY);
INSERT INTO col VALUES
  (1), (2), (3), (4), (5), (6), (7), (8), (9)
;

です。

FROM句による直積の確認

FROM は直積を取りたい集合(テーブル)名をカンマ区切りで書きます。

FROM テーブル1, テーブル2, ...

横に並べると、数が増えた時に読みづらいので縦に並べることが多いです。

FROM
  テーブル1,
  テーブル2,
  ...

この書き方は、他の句でも使われます。
今回の確認を行うSQLは以下となります。
SQL

SELECT
  *
FROM
  col,
  row
;

結果

c r
1 1
2 1
3 1
~ 中略 ~
9 1
1 2
2 2
3 2
~ 中略 ~
9 2
1 3
2 3
3 3
~ 中略 ~
7 9
8 9
9 9

直積を取った集合が新しく作られたのが確認できます。

WHEREによる部分集合作成の確認

つぎは、この中から平方数を生み出すレコードのみを元に持つ部分集合を抽出してみます。
今回は、乗数と被乗数が等しいレコードから成る部分集合を作ります。
SQL

SELECT
  *
FROM
  col,
  row
WHERE
  col.c = row.r  -- 要素へアクセスする場合は . でフィールド名を添える
;

結果

c r
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9

乗数と被乗数が同じレコードのみを元として持つ部分集合となりました。

SELECTによる写像の確認

先ほどまで使っていた “SELECT * ” は、恒等写像を表します。

レコードそのものもタプルである為、これを繰り返すと階層が深くなり扱いづらくなります。
そこで、 今回は、被乗数、乗数、乗算結果 を要素として持つレコードとしたいので、それを定義します。
SQL

SELECT
  col.c,                -- AS を省略した場合は同じフィールド名となる
  row.r,
  col.c * row.r AS res  -- AS で新しいフィールド名を指定できる
FROM
  col,
  row
WHERE
  col.c = row.r
;

結果

c r res
1 1 1
2 2 2
3 3 9
4 4 16
5 5 25
6 6 36
7 7 49
8 8 64
9 9 81

全てのレコードについて、SELECTで指定した写像が適用されているのが確認できます。

おわりに

自分がSQLに初めて触れた時、こう説明してほしかったなぁと思っていたことを書いてみました。
また、このような理解でSQLを習得すると、JavaのStreamやC#Linqへつなげることができます。
せっかく身に付けるのであれば、その分野でしか使えないような覚え方でなく、他につながる覚え方をしたいですね!

FWと聞いて

 あなたは何の略だと思いましたか?

ファームウェアFirmware)だと思ったあなた

"FW IT" でググると最初に出てくるからこの業界では恐らく最も一般的な解釈ですよ!
 きっと組み込み屋さんですね。  この"FW"は他の"FW"に比べて地位が低いと思うのは気のせいでしょうか。。。
 工程遅延のしわ寄せはすべてファームに来るし、量産機の評価で見つかったハード要因の不具合もできる限り吸収させられるし、フィールドで出た不具合はアクチュエータもセンサも無くてどう考えても拾えないのに何とかしろと怒られる!
 熱がこもりすぎました。
 ファームウェアは寝ず*1ろくに食事もとらず*2仕事しているので思考が鈍り*3痩せ衰えた*4社畜の鏡のような存在です。
 労わって接してあげましょう。

ファイヤーウォール(Firewall)だと思ったあなた

 上記のワードでググると二番目に出てくるので割と一般的な解釈!
 インフラ屋さんに聞くと大体この答えが返ってきます。
 でも、ITに関係する人なら一般教養レベルで知っておかなければならないもの。
 自身のコンピュータにとって、受け取ったデータを"受信していい"といった意味でなく"受信したくない"といった意味において*5最初に弾いてくれる、Noと言える素敵なお方。
 自己主張ができることは大変魅力的なのですが、時にはやり過ぎちゃうこともあるので定義を見直してしっかりと手綱を握ってあげましょう。

フレームワーク(Framework)だと思ったあなた

 上記(ryで三番目に出てくる解釈!
 アプリ屋さんに多いのかな?
 自分がコーディングすることなく後ろで知らないうちに制御を組み立ててくれるお世話好きさん。
 その力は強力で、これ無しではなにも書けないという骨抜きにされたPGも数知れず。
 中身はブラックボックスでよくわかんないけどもやってくれるすごいやつ!って感じでヒモになるのではなく、プレーンな状態の言語と向き合ってなにをお世話してくれているのか察して、その上でお世話させてあげる大人の余裕を見せてあげましょう。

フィールドワーク(Fieldwork)だと思ったあなた

 企画関係の方や、外で研究する学者さんなどが多いのでしょうか?
 今後の方針や期待の裏付けなどを行ってくれる、デキる人です。
 こうであってほしいなどの願望を押し付けるのではなく、自然体で接してすべてを受け入れられるような懐の深いところを見せてあげましょう。

フォワード(メール)だと思ったあなた

 IT業界を離れるときっと最も一般的です。
 場合によっては自分だけでなく会社の立場も危うくなるような、危険性を持ち合わせた存在です。
 転送メールは特に、転送して問題のない内容であるかの確認をしっかりしましょう。

フォワード(スポーツ)だと思ったあなた

 球技には大体こう言われるポジションがありますね。
 攻撃的なポジションであることが多いです。
 積極的で前のめりな熱いところがみんなの心をつかむ、魅力的な存在です。
 でも、心は人一倍クールでいてほしいものです。

 略語は、同じ文字の並びでも、使われる分野・状況応じて意味を変化させます。
 使う側は現在の状況や相手の持っている知識を考えて正しく伝わるか、もし間違えてとらえていたら自分の言葉がどのような解釈へ変わるかを意識し、
受け取る側は逆に文脈や相手の知識から、何を言おうとしているのかを考えたいものです。

*1:稼働時間的な意味で

*2:消費電力的な意味で

*3:CPUクロック的な意味で

*4:プロセッサのフラッシュ容量、積載されているメモリ的な意味で

*5:ACLMACアドレスフィルタリングはコンピュータより外にあるのでおいとく

Java Decoratorの装飾関係をリストで表現する

はじめに

 Decorator パターンにおいて、 Component と Decorator は Component を親の階層に持つ 1 : 1 の関係にあります。
 子ノードが常に一つの木構造を想像すると近いと思います。
 元から使いやすいパターンではありますが、この "階層を持つ" というのが曲者で扱いづらく感じる
場合があります。
 そこで、子ノードが一つの木はリスト構造をほぼ同等である為、この階層をリストにすることが
できるのではないかと思いつきました。

リスト構造がいい理由

 リスト構造にすると何が嬉しいかは、
1. Decoratorを適用する際、関係が縦でなく横となる為、インデントがそろい読みやすい
2. Decorator コンストラクタへの引数が読みやすい
3. 装飾階層に対して、Decorator の挿入・削除が容易に行える
4. Stream によって適用する Decorator を選択できる
などがあります。
 Decorator を適用する際、

new Decorator3(
  new Decorator2( true
    new Decorator1( 10,
      new Component()
    )
  )
);

のように、コンストラクタの中でインスタンス化を行う為、階層が深くなります。
 これを、

DecorateList deco = new DecorateList(){
  {
    new Component(),
    new Decorator1(),
    new Decorator2(true),
    new Decorator3(10)
  }
};

のような形で記憶しておき、利用の直前に関連付けがなされたComponentのインスタンスを得ることが目標です。

ソース

DecorateList.java

package decorator;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.function.*;
import java.util.stream.*;

public class DecorateList<C> extends ArrayList<Function<C, ? extends C>>
{
    private static class GeneralContainer<T>
    {
        public static <T> GeneralContainer<T> create(T value)
        { return new GeneralContainer<T>(value); }
        
        public T value;
        public GeneralContainer(T value)
        { this.value = value; }
    }
    
    public static <C> Collector<Function<C, ? extends C>, GeneralContainer<C>, C> toComponent(C init)
    {
        return Collector.<Function<C, ? extends C>, GeneralContainer<C>, C>of(
            () -> GeneralContainer.create(init),
            (c, f) -> c.value = f.apply(c.value),
            (c1, c2) -> null,
            c -> c.value
        );
    }
    
    @SafeVarargs
    public static <C> DecorateList<C> create(Function<C, ? extends C>... args)
    { return new DecorateList<C>(args); }
    @SafeVarargs
    public static <C> DecorateList<C> createFromDecorable(Decorable<C>... args)
    { return new DecorateList<C>(Arrays.stream(args).map( d -> d::attach )); }
    
    public DecorateList()
    { }
    
    public DecorateList(List<Function<C, ? extends C>> attachList)
    { super(attachList); }
    @SafeVarargs
    public DecorateList(Function<C, ? extends C>... args)
    { this(Arrays.asList(args)); }
    public DecorateList(Stream<Function<C, ? extends C>> stream)
    { this(stream.collect(Collectors.toList())); }
    
    public C getDecorated(C init)
    {
        C current = init;
        for(Function<C, ? extends C> item : this)
        {
            current = item.apply(current);
        }
        return current;
    }
}

Decorable.java

package decorator;

public interface Decorable<C>
{
    C attach(C parent);
}

 こんな感じになりました。
 ArrayList を継承させることで装飾の関係がいじりやすそうですね。
 使い方は、

// case normal decorator
DecorateList<Component> decoList = DecorateList.create(
    com -> new Decorator1(com),
    com -> new Decorator2(com),
    com -> new Decorator3(com)
);
Component component = decoList
    .stream()
    .limit(2)
    .collect(DecorateList.toComponent(new ConcreteComponent()));
// case decorable
DecorateList<DecorableComponent> decorableList = DecorateList.createFromDecorable(
    new DecorableDecorator1(),
    new DecorableDecorator2(),
    new DecorableDecorator3()
);
DecorableComponent component = decorableList
    .stream()
    .limit(2)
    .collect(DecorateList.toComponent(new ConcreteDecorableComponent()));

 のようになります。
 装飾の階層関係が順序関係に置き換わり読みやすい上に、stream の恩恵もばっちり受けることができます。
 Decorator の "組み立て方" を教えることによって、既存のソースに手を加えることなく利用することもできます。
 だいぶすっきりするので、使ってみてください。

Java Decoratorパターンが何かに似ていると引っかかった

はじめに

 今回はGoFデザインパターンの一つである "Decoratorパターン" について考察します。
 なぜ Decorator であるかの理由は、最近たまたま出てきて引っ掛かりを覚えたからです。
 ごちゃごちゃした内容になります。

2016/07/29大部分修正

 下書きで保存しておいたつもりが公開してました、ごめんなさい。
 修正個所がわからなくなりますが、多すぎて読みづらくなるので消して書き直しまくります。

普通にDecoratorパターン

 クラス図を書くほどでもないのでソースで提示します。
Component.java

public interface Component
{ int operation(); }

ConcreteComponent.java

public class ConcreteComponent implements Component
{
    public int operation()
    { return 10; }
}

Decorator.java

public abstract class Decorator implements Component
{
    protected Component parent;
    public Decorator(Component parent)
    { this.parent = parent; }
    public abstract int operation();
}

ConcreteDecorator.java

public class ConcreteDecorator extends Decorator
{
    public ConcreteDecorator(Component parent)
    { super(parent); }
    public int operation()
    { return super.parent.operation() * 2; }
}

 振る舞いは適当に書きましたが、こんな関係でしたね。
 ConcreteComponent と ConcreteDecorator が共に Componentインタフェース を実装している為、外から見た機能は同じように扱え、 ConcreteComponent に行き着くまで再帰的に ConcreteDecorator の装飾処理を行うことが特徴でした。

何かに似ている?

 上記の実装で利用するときのソースはこうなります。
 ConcreteDecorator で三回装飾します。

Component component =
    new ConcreteDecorator(
        new ConcreteDecorator(
            new ConcreteDecorator(
                new ConcreteComponent()
            )
        )
    );
System.out.println(component.operation());

 ここからは、部分部分でのシグネチャに注目します。
 シグネチャの示したかは以下の書式で示し、カリー化されているものとします。

# 何のシグネチャかに関する説明
    第一引数の型 -> 第二引数の型 -> ... -> 第m引数の型 -> 戻り値の型
# 引数が無い場合
    戻り値の型
# 明示的に引数がないことを示す場合
    () -> 戻り値の型
# 戻り値が無い(void)の場合
    引数の型 -> ()
# 外側から見えない、状態などから値を得ている場合
  引数の型 -> { 状態の型1 -> 状態の型2 -> ... -> 状態の型n } -> 戻り値の型

 まず、メソッド呼び出しとメソッド内の式について考えます。  

# メソッド int operation() のシグネチャ
    () -> int
# operation内の式 super.parent.operation() * 2 のシグネチャ
# "* 2" を値に対する操作であると考えて
    int -> (int -> int) -> int

 比較すると、どこからともなく int 型の値が一つと、これを操作する関数が現れたことがわかります。
 渡されたわけではない為、文脈と関係のない "状態" とでも呼ぶべき場所から値を得たことになります。
 では、この状態を作っているのはどこであるかを考えてみます。
 それはズバリ、インスタンス化している場所ですね。
 ConcreteComponent は内部に int 型の値を保持しており、Decorator を継承するクラスは Component のインスタンスと int から int への関数を保持しています。
 つまり、operation のみに着目してインスタンス化~メソッド呼び出しまでを一つの系と考えると、

# 装飾なし
# new ConcreteComponent().operation()
    () ->
      { int }
         -> int
# 装飾が一回
# new ConcreteDecorator(
#     new ConcreteComponent()
# ).operation()
    () -> 
      { int
        -> (int -> int) }
          -> int
# 装飾が二回
# new ConcreteDecorator(
#     new ConcreteDecorator(
#         new Concrete()
#     )
# ).operation()
    () ->
      { int 
        -> (int -> int)
        -> (int -> int) }
          -> int
# 装飾が三回
# new ConcreteDecorator(
#     new ConcreteDecorator(
#         new ConcreteDecorator(
#             new Concrete()
#         )
#     )
# ).operation()
    () ->
      { int 
        -> (int -> int)
        -> (int -> int)
        -> (int -> int) }
          -> int

 という経路を辿っていることがわかります。
 ここで、装飾する度に増えていく

    (int -> int) -> (int -> int)

とはいったい何でしょう?
 シグネチャに対応する部分をJavaラムダ式で考えると

Function<int, int> operation1;
Function<int, int> operation2; 

// ConcreteComponent に近いものから順番に適用される
Function<int, int> f = num -> operation2(operation1(num));
// 書き換えて
Function<int, int> f_ = operation1.andThen(operation2);

となります。
 つまり、関数の合成を行っていることとなります。
 何かに似ていると感じたのは、合成関数だったのです。

Decoratorパターンを合成関数で表現

 それでは始めに実装した Decorator パターンでの operation と同じ挙動を合成関数で表現してみます。

void run()
{
    Supplier<int> concreteComponent = () -> 10;
    Function<int, int> concreteDecorator = num -> num + 2;
    
    Supplier<int> decorated = () ->
        concreteDecorator
            .andThen(concreteDecorator)
            .andThen(concreteDecorator)
            .apply(concreteComponent.get());

/*
//  Supplier に 以下のような andThen メソッドが定義されていれば
    interface Supplier<T>
    {
        <R> Supplier<R> andThen(Function<T, R> f)
        { return () -> f.apply(get()); }
    }

//  このように書ける
    Supplier<int> decorated =
        concreteComponent
            .andThen(concreteDecorator)
            .andThen(concreteDecorator)
            .andThen(concreteDecorator);
*/

    System.out.println(decorated.get());
}

 Supplier にも andThen の定義があれば綺麗になります。
 concreteDecorator の定義を変えてどんどん合成していけば型を変えずに元の処理をどんどん装飾していけますね!

おわりに

 今回は Decorator パターンに関してのみ考えましたが、再帰的な構造とポリモーフィズムによる終端の組み合わせを利用したパターンは多分ですがこれと同じ論法で合成関数との類似性を示すことができると思います。(例えば Composite パターンとか)
 オブジェクト指向関数型言語の考え方が当たり前のように利用されている今だからこそ、改めて新しい視点からデザインパターンを見つめることも有用だと感じました。
 なお、ここで書いたソースのほとんどはベタで書きなぐったものであり、コンパイルしておらず、動作の保証はできません。

 次のエントリも Decorator パターンについて書く予定です。

Java Tupleの実装

はじめに

 Javaには二つの型を格納できる Tuple しか標準ライブラリには存在しないようです。
 不便なので動きやすくするためにとりあえず10個の型引数までに対応した Tuple を作ります。

実装方法

 実装方法について、
1. 型引数の数に対して1つずつクラスを定義していく
2. リスト構造をとり、クラスそのものは一つの定義とする

の二通りが考えられましたが、今回は1番の方法で実装することにします。
 今回は10個の型に対応した Tuple までを実装しますが、人力で実装していては変なバグを作りこむ可能性があります。
 そして何よりめんどくさいです。
 幸いにもこれらのソースは構造を持った文字列になる為、プログラムを書くプログラムを実装します。  今回はさくっと書ける Ruby で実装しました。
 また、2番の方法ですでに実装した先人がおられるのでリンクを張っておきます。
qiita.com

ソース

 はじめにソースを生成するRubyのソースを載せます。
TupleMaker.rb

#tuple maker
Package = "tuples"
Tuples = ["Single", "Pair", "Triple", "Quadruple", "Quintuple",
          "Sextuple", "Septuple", "Octuple", "Nonuple", "Decuple"]

def makePackage(package)
  "package " + package + ";\n"
end
def makeImport(import)
  "import " + import + ";\n"
end

def makeFields(len)
  ret = ""
  len.times{|i|
    ret += "    private final I" + (i + 1).to_s + " _item" + (i + 1).to_s + ";\n"
  }
  ret
end

def makeTypeArgs(len)
  ret = "<"
  (len - 1).times{|i|
    ret += "I" + (i + 1).to_s + ", "
  }
  ret += "I" + len.to_s + ">"
end

def makeArgs(len, hasType)
  ret = "("
  (len - 1).times{|i|
    ret += (hasType ? "I" + (i + 1).to_s  + " ": "") + "item" + (i + 1).to_s + ", "
  }
  ret += (hasType ? "I" + len.to_s  + " ": "") + "item" + len.to_s + ")"
end
def makeCreate(className, len)
  "    public static " + makeTypeArgs(len) + " " +
    className + makeTypeArgs(len) + " create" + makeArgs(len, true) + "\n" +
  "    {\n" +
  "        return new " + className + makeTypeArgs(len) + makeArgs(len, false) + ";\n" +
  "    }\n"
end

def makeConstractor(className, len)
  ret = "    private " + className + makeArgs(len, true) + "\n"
  ret += "    {\n"
  
  (len - 1).times{|i|
    ret += "        this._item" + (i + 1).to_s + " = item" + (i + 1).to_s + ";\n"
  }
  ret += "        this._item" + len.to_s + " = item" + len.to_s + ";\n"
  ret += "    }\n"
end

def makeGetter(len)
  ret = ""
  len.times{|idx|
    i = idx + 1
    ret += "    public I" + i.to_s + " item" + i.to_s + "()\n"
    ret += "    { return this._item" + i.to_s + "; }\n"
  }
  ret
end

def makeCurry(len, index, last)
  index >= len ?
    last:
  # otherwise
    "Function<I" + (index + 1).to_s + ", " + makeCurry(len, index + 1, last) + ">"
end
def makeUseCurry(len, index, last)
  index >= len ?
    last:
  # otherwise
    ".apply(this._item" + (index + 1).to_s + ")" + makeUseCurry(len, index + 1, last)
end
def makeAccept(className, len)
  "    public " + className + makeTypeArgs(len) + " accept" + "(" + 
    makeCurry(len - 1, 0, "Consumer<I" + len.to_s + ">") + " f)\n" +
  "    {\n" +
  "        f" + makeUseCurry(len - 1, 0, ".accept(this._item" + len.to_s + ")") + ";\n" +
  "        return this;\n" +
  "    }\n"
end
def makeApply(len)
  "    public <R> R apply(" + makeCurry(len - 1, 0, "Function<I" + len.to_s + ", R>") + " f)\n" +
  "    {\n" +
  "        return f" + makeUseCurry(len - 1, 0, ".apply(this._item" + len.to_s + ")") + ";\n" +
  "    }\n"
end

def makeClass(packageName, className, len)
  makePackage(packageName) + "\n" +
  makeImport("java.util.function.*") +
  "\n" +
  "public class " + className + makeTypeArgs(len) + "\n" +
  "{\n" +
  makeFields(len) + "\n" +
  makeCreate(className, len) + "\n" +
  makeConstractor(className, len) + "\n" +
  makeGetter(len) + "\n" +
  makeAccept(className, len) +
  makeApply(len) +
  "}\n"
end

def makeTupleClass(tuples, package)
  ret = makePackage(package) + "\n" +
        "public final class Tuple\n" +
        "{\n" +
        "    private Tuple()\n" +
        "    { }\n"

  tuples.each_with_index{|tp, idx|
    i = idx + 1
    ret += "\n"
    ret += "    public static " + makeTypeArgs(i) + " " + tp +
             makeTypeArgs(i) + " create" + makeArgs(i, true) + "\n"
    ret += "    { return " + tp + ".create" + makeArgs(i, false) + "; }\n"
    
    open(tp + ".java", "w"){|f|
      f.puts makeClass(package, tp, i)
    }
  }
  ret += "}\n"
  
  open("Tuple.java", "w"){|f|
    f.puts ret
  }
  
end

makeTupleClass(Tuples, Package)

 使い捨てのソースなんてきっとみんなこんなものです、汚かったり効率が悪いのは目をつむってください。
 実行前後のディレクトリはこのようになります。

X:\tuples>dir
 ドライブ X のボリューム ラベルは Windows です
 ボリューム シリアル番号は ****-**** です

 X:\tuples のディレクトリ

2016/07/27  21:26    <DIR>          .
2016/07/27  21:26    <DIR>          ..
2016/07/27  21:18             3,650 TupleMaker.rb
               1 個のファイル               3,650 バイト
               2 個のディレクトリ  **,***,***,*** バイトの空き領域

X:\tuples>ruby TupleMaker.rb

X:\tuples>dir
 ドライブ X のボリューム ラベルは Windows です
 ボリューム シリアル番号は ****-**** です

 X:\tuples のディレクトリ

2016/07/27  21:22    <DIR>          .
2016/07/27  21:22    <DIR>          ..
2016/07/27  21:18             2,611 Decuple.java
2016/07/27  21:18             2,365 Nonuple.java
2016/07/27  21:18             2,140 Octuple.java
2016/07/27  21:18               775 Pair.java
2016/07/27  21:18             1,250 Quadruple.java
2016/07/27  21:18             1,475 Quintuple.java
2016/07/27  21:18             1,920 Septuple.java
2016/07/27  21:18             1,695 Sextuple.java
2016/07/27  21:18               560 Single.java
2016/07/27  21:18             1,010 Triple.java
2016/07/27  21:18             2,120 Tuple.java
2016/07/27  21:18             3,650 TupleMaker.rb
              12 個のファイル              21,571 バイト
               2 個のディレクトリ  **,***,***,*** バイトの空き領域

 次に、生成したソースを載せます。
 Tupleの具体的な定義は種類が多い為、3個の型を扱う "Tripleクラス" と 10個の型を扱う "Decupleクラス" の二つを載せます。
Tuple.java

package tuples;

public final class Tuple
{
    private Tuple()
    { }

    public static <I1> Single<I1> create(I1 item1)
    { return Single.create(item1); }

    public static <I1, I2> Pair<I1, I2> create(I1 item1, I2 item2)
    { return Pair.create(item1, item2); }

    public static <I1, I2, I3> Triple<I1, I2, I3> create(I1 item1, I2 item2, I3 item3)
    { return Triple.create(item1, item2, item3); }

    public static <I1, I2, I3, I4> Quadruple<I1, I2, I3, I4> create(I1 item1, I2 item2, I3 item3, I4 item4)
    { return Quadruple.create(item1, item2, item3, item4); }

    public static <I1, I2, I3, I4, I5> Quintuple<I1, I2, I3, I4, I5> create(I1 item1, I2 item2, I3 item3, I4 item4, I5 item5)
    { return Quintuple.create(item1, item2, item3, item4, item5); }

    public static <I1, I2, I3, I4, I5, I6> Sextuple<I1, I2, I3, I4, I5, I6> create(I1 item1, I2 item2, I3 item3, I4 item4, I5 item5, I6 item6)
    { return Sextuple.create(item1, item2, item3, item4, item5, item6); }

    public static <I1, I2, I3, I4, I5, I6, I7> Septuple<I1, I2, I3, I4, I5, I6, I7> create(I1 item1, I2 item2, I3 item3, I4 item4, I5 item5, I6 item6, I7 item7)
    { return Septuple.create(item1, item2, item3, item4, item5, item6, item7); }

    public static <I1, I2, I3, I4, I5, I6, I7, I8> Octuple<I1, I2, I3, I4, I5, I6, I7, I8> create(I1 item1, I2 item2, I3 item3, I4 item4, I5 item5, I6 item6, I7 item7, I8 item8)
    { return Octuple.create(item1, item2, item3, item4, item5, item6, item7, item8); }

    public static <I1, I2, I3, I4, I5, I6, I7, I8, I9> Nonuple<I1, I2, I3, I4, I5, I6, I7, I8, I9> create(I1 item1, I2 item2, I3 item3, I4 item4, I5 item5, I6 item6, I7 item7, I8 item8, I9 item9)
    { return Nonuple.create(item1, item2, item3, item4, item5, item6, item7, item8, item9); }

    public static <I1, I2, I3, I4, I5, I6, I7, I8, I9, I10> Decuple<I1, I2, I3, I4, I5, I6, I7, I8, I9, I10> create(I1 item1, I2 item2, I3 item3, I4 item4, I5 item5, I6 item6, I7 item7, I8 item8, I9 item9, I10 item10)
    { return Decuple.create(item1, item2, item3, item4, item5, item6, item7, item8, item9, item10); }
}

Triple.java

package tuples;

import java.util.function.*;

public class Triple<I1, I2, I3>
{
    private final I1 _item1;
    private final I2 _item2;
    private final I3 _item3;

    public static <I1, I2, I3> Triple<I1, I2, I3> create(I1 item1, I2 item2, I3 item3)
    {
        return new Triple<I1, I2, I3>(item1, item2, item3);
    }

    private Triple(I1 item1, I2 item2, I3 item3)
    {
        this._item1 = item1;
        this._item2 = item2;
        this._item3 = item3;
    }

    public I1 item1()
    { return this._item1; }
    public I2 item2()
    { return this._item2; }
    public I3 item3()
    { return this._item3; }

    public Triple<I1, I2, I3> accept(Function<I1, Function<I2, Consumer<I3>>> f)
    {
        f.apply(this._item1).apply(this._item2).accept(this._item3);
        return this;
    }
    public <R> R apply(Function<I1, Function<I2, Function<I3, R>>> f)
    {
        return f.apply(this._item1).apply(this._item2).apply(this._item3);
    }
}

Decuple.java

package tuples;

import java.util.function.*;

public class Decuple<I1, I2, I3, I4, I5, I6, I7, I8, I9, I10>
{
    private final I1 _item1;
    private final I2 _item2;
    private final I3 _item3;
    private final I4 _item4;
    private final I5 _item5;
    private final I6 _item6;
    private final I7 _item7;
    private final I8 _item8;
    private final I9 _item9;
    private final I10 _item10;

    public static <I1, I2, I3, I4, I5, I6, I7, I8, I9, I10> Decuple<I1, I2, I3, I4, I5, I6, I7, I8, I9, I10> create(I1 item1, I2 item2, I3 item3, I4 item4, I5 item5, I6 item6, I7 item7, I8 item8, I9 item9, I10 item10)
    {
        return new Decuple<I1, I2, I3, I4, I5, I6, I7, I8, I9, I10>(item1, item2, item3, item4, item5, item6, item7, item8, item9, item10);
    }

    private Decuple(I1 item1, I2 item2, I3 item3, I4 item4, I5 item5, I6 item6, I7 item7, I8 item8, I9 item9, I10 item10)
    {
        this._item1 = item1;
        this._item2 = item2;
        this._item3 = item3;
        this._item4 = item4;
        this._item5 = item5;
        this._item6 = item6;
        this._item7 = item7;
        this._item8 = item8;
        this._item9 = item9;
        this._item10 = item10;
    }

    public I1 item1()
    { return this._item1; }
    public I2 item2()
    { return this._item2; }
    public I3 item3()
    { return this._item3; }
    public I4 item4()
    { return this._item4; }
    public I5 item5()
    { return this._item5; }
    public I6 item6()
    { return this._item6; }
    public I7 item7()
    { return this._item7; }
    public I8 item8()
    { return this._item8; }
    public I9 item9()
    { return this._item9; }
    public I10 item10()
    { return this._item10; }

    public Decuple<I1, I2, I3, I4, I5, I6, I7, I8, I9, I10> accept(Function<I1, Function<I2, Function<I3, Function<I4, Function<I5, Function<I6, Function<I7, Function<I8, Function<I9, Consumer<I10>>>>>>>>>> f)
    {
        f.apply(this._item1).apply(this._item2).apply(this._item3).apply(this._item4).apply(this._item5).apply(this._item6).apply(this._item7).apply(this._item8).apply(this._item9).accept(this._item10);
        return this;
    }
    public <R> R apply(Function<I1, Function<I2, Function<I3, Function<I4, Function<I5, Function<I6, Function<I7, Function<I8, Function<I9, Function<I10, R>>>>>>>>>> f)
    {
        return f.apply(this._item1).apply(this._item2).apply(this._item3).apply(this._item4).apply(this._item5).apply(this._item6).apply(this._item7).apply(this._item8).apply(this._item9).apply(this._item10);
    }
}

 10個の型引数とこれのカリー化された式にもなると、人の手で記述したときに絶対と断言していいほどミスをしそうですね。
 Tupleクラスは、 createメソッド をオーバーロードすることで利用者に対して汎用型そのものの違いを意識させず、型推論させることで面倒な型引数の記述を省きます。
 acceptメソッド と applyメソッド を用意したいが為に、先ほど示した2種類の実装方法から1番を選択しました。
 このメソッドを用意しておくことで、

String test = Tuple
    .create(1, "に", true)
    .apply( num -> str -> flag ->
        Tuple.create(str + num.toString(), flag) )
    .apply( str -> flag -> flag ? str + str : str );

のような形で、わざわざそれぞれにアクセスせず展開できます。
 haskellなどの言語で、パターンマッチングによりタプルから要素を取り出すのに似ていますね。

t = (1, "two", True)
(num, str, flag) = t
str' = str ++ show(num)
str'' | flag      = str' ++ str'
      | otherwise = str'

 また、メソッドチェーンを繰り返すことで利用中に Pair と Triple というクラス名が一度も出てこず、引数をラムダ式で記述することにより扱っている値の型も明示が不要となります。

おわりに

 Tupleは一度使うと中毒性があります。
 シチュエーションとしては、メソッドチェーン中に複数の値を次のチェーンへ渡したい場合などが多いと思います。
 Javaではないと聞いてがっかりしそうになりました。
 でも、限定的ではあるものの型推論の機能が備わっている為、むしろ限定的であることが作用していかに推論させるかを考えた結果として使い勝手もそれなりのものができたと思います。

 次はJavaっぽく、Decoratorパターンを詰めて考えた結果を書きたいと思います。

Java 推論型を利用したい

はじめに

 今後Javaを使うことがほぼ確定となったため勉強します。
 でもいい題材がないので思いついたものやJavaで不便に感じることを解消する形のものを実装しつつ、Javaをつかんでいきたいと思います。

実装内容

 Javaでは推論型が基本的に使えません。
 しかしこれには例外があり、"ラムダ式の引数と処理を区切る -> 演算子の左側" では型が推論できる状況であれば明示しなくても問題ありません。
 ラムダ式を与えて処理し続ければ型宣言は不要となります。
 これは常に同じようなクラスを返し続ければ実現でき、これを満たすのはジェネリクス型のメソッドチェーンですね。
 格納した値に直接触れずに、処理だけ渡して影響させ続けるというのはどこかで聞いたことがあります。
 Haskellでいうと Functorクラス の fmap関数 がこのような仕事をしていました。
 C#から考えると、Linq での IEnumerable<T>型 に対する Select拡張メソッド も同じですね。
 それでは、実際に実装してみたいと思います。

実装

import java.util.function.*;

public class Chain<V>
{
    public static <V> Chain<V> create(V value)
    {
        return new Chain<V>(value);
    }
    
    private V value;
    
    private Chain(V value)
    {
        this.value = value;
    }
    
    public V get()
    {
        return this.value;
    }
    
    public Chain<V> accept(Consumer<V> f)
    {
        f.accept(this.value);
        return this;
    }
    public Chain<V> accept(BiConsumer<Chain<V>, V> f)
    {
        f.accept(this, this.value);
        return this;
    }
    
    public <R> Chain<R> apply(Function<V, R> f)
    {
        return Chain.create(f.apply(this.value));
    }
    public <R> Chain<R> apply(BiFunction<Chain<V>, V, R> f)
    {
        return Chain.create(f.apply(this, this.value));
    }

    public boolean test(Predicate<V> f)
    {
        return f.test(this.value);
    }

    public <R> Chain<R> bind(Function<V, Chain<R>> f)
    {
        return f.apply(this.value);
    }
    public <R> Chain<R> bind(BiFunction<Chain<V>, V, Chain<R>> f)
    {
        return f.apply(this, this.value);
    }
}

 実装してみると、綺麗に何もしないモナドが作れそうだったのでついでに bind メソッドも作っておきました、が、このbindは実際に使うことはなさそうです。
 モナドを作るのがメインではなかったので、関数の対応のみ軽く書いておきます。
  return = create
  bind = bind
  (fmap = apply)
 それでは、実際に使ってみます。

public class Test
{
    public static void main(String[] args)
    {
        System.out.println(
            Chain
                .create(20)                                 // 初期値、型の宣言が不要
                .apply( num -> "num = " + num.toString() )  // ラムダ式を渡すことによる間接的な操作
                .accept( str -> System.out.println(str) )   // アクションの実行
                .apply( str -> str + " test" )              // もう一度操作
                .get()                                      // 値を取り出す
        );
    }
}

結果

num = 20
num = 20 test
続行するには何かキーを押してください . . .

 メソッドチェーンを続けている間は型宣言なしで操作し続けることができましたね。
 これで入れ子になったジェネリクス型を扱うときなどに楽そうです!

おわりに

 C#やってるからJavaもすぐできると思っていましたが、細かい違いが意外と目に付いて頭になじむまでは少しかかりそうです。
 特に大きな違いとして、ジェネリクス型を扱うとき、型引数の数のみが違うクラスやメソッドが扱えない点が挙げられます。
 次は、この違いが大きく出る Tuple の実装を行ってみたいと思います。
 またこの Tuple は型が非常にややこしくなる為、今回実装した Chainクラス に本領を発揮してもらいたいと思います。

2016/7/27追記

 Tuple のエントリでは使いませんでした!!
 でもここでの推論させ方がそのまま利用されており、こちらの Chainクラス と組み合わせて使う場合も想像できるのではないかと思います。