08 Dec 2014, 13:52

Java で Iterator Pattern を実装してみた

はじめに

最近, Gof のデザインパターンをすべて記事にしようと考えている.

そんなわけで, 今日は Iterator パターン. あまりに基本すぎて, 記事にするほどではないがするが…

Iterator パターンとは

オブジェクトの集合 (データ構造, コンテナ) があるとき, その集合の内部構造はカプセル化したままで, 要素に対して順にアクセスする方法を提供する.

コンテナオブジェクトの要素を列挙する手段を独立させることによって, コンテナの内部仕様に依存しない反復子を提供することを目的とする.

言語でサポートしていることがおおい. 拡張 for 文, for-each 文などと呼ばれる.

自前で実装するよりも, 言語に頼るほうがよい.

Java

Collection フレームワークでは, 反復子が利用できる.

List<Integer> list = LinkedList<Integer>
for (int i; list) {
System.out.println (i);
}

Iterator インタフェースを実装することで, 自前のクラスにイテレータを適用できる.

Iterator interface を実装する.

Iterator interface を実装した.

import java.util.Iterator;

public class IteratorSample {
    public static void main (String args[]) {
        myList list = new myList (1, new myList (2, new myList (3, null)));

        while (list.hasNext ()) {
            list.show ();
            list = list.next ();
        } 
        list.show ();
    }
}

class myList implements Iterator {
    myList next;
    int value;

    public myList (int value, myList next) {
        this.value = value;
        this.next = next;
    }

    @Override
    public boolean hasNext () {
        return (next != null);
    }

    @Override
    public myList next () {
        return next;
    }

    @Override
    public void remove () {
        // nop
    }

    public void show () {
        System.out.println (value);
    }
}

自前で hasNext, next メソッドを用意するよりも, Iterator interface を実装したほうが, 通に思われるというメリットがある.

関数型 Iterator パターン

関数型 Iterator パターンみたいなものを考えた. というよりも List の実装.

  • while を利用するのではなくて, 再帰を利用する.
import java.util.Iterator;

public class IteratorSample2 {
    public static void main (String args[]) {
        myList list = new myList (1, new myList (2, new myList (3, null)));
        whileLoop (list);
    }

    static void whileLoop (myList list) {
        list.show ();
        if (!list.hasNext ())
            return;
        else { 
            whileLoop (list.next ());
        }
    }
}

class myList implements Iterator<myList> {
    myList next;
    int value;

    public myList (int value, myList next) {
        this.value = value;
        this.next = next;
    }

    @Override
    public boolean hasNext () {
        return (next != null);
    }

    @Override
    public myList next () {
        return next;
    }

    @Override
    public void remove () {
        // nop
    }

    public void show () {
        System.out.println (value);
    }
}

なんか, 再帰のほうがいいな.おそまつさまでした.

07 Dec 2014, 15:33

Java で Chain of Responsibility Pattern を 末尾再帰で実装した

はじめに

Chain of Responsibility Pattern という, マイナーな Gof のパターンがある.

本をよんでみて, これって再帰関数を利用すればもっとシンプルにかけるん じゃないかとおもって, 試してみた.

Chain of Responsibility Pattern

責務を持たせたオブジェクトの Chain に 要求を渡していく.

要求は,

  • そのオブジェクトで処理できればそこで処理する
  • そのオブジェクトで処理できなければ, 次のオブジェクトに渡す.

パターン未適用

[sourcecode language=”java” title=””]
import java.util.List;
import java.util.LinkedList;

public class ChainOfResponsibilitySample {
public static void main (String[] args) {
List chain = new LinkedList();
chain.add (new A ());
chain.add (new B ());
chain.add (new C ());

for (Handler handler : chain) {
if (handler.isMatch (‘b’)) {
handler.execute ();
break;
}
}
}
}

abstract class Handler {
public abstract boolean isMatch (char c);
public abstract void execute ();
}

class A extends Handler {
public boolean isMatch (char c) { return c == ‘a’; }
public void execute () { System.out.println ("a hit"); }
}

class B extends Handler {
public boolean isMatch (char c) { return c == ‘b’; }
public void execute () { System.out.println ("b hit"); }
}

class C extends Handler {
public boolean isMatch (char c) { return c == ‘c’; }
public void execute () { System.out.println ("c hit"); }
}
[/sourcecode]

絶望ポイント

<div class="outline-text-3" id="text-unnumbered-4">
  <p>
    ここがきたない.
  </p>

  <p>
    制御側からいちいち判定用メソッドを読んだり, マッチしたらアクションを起動している.これが面倒.
  </p>

  <p>
    [sourcecode language=&#8221;java&#8221; title=&#8221;&#8221;]<br /> for (Handler handler : chain) {<br /> if (handler.isMatch (&#8216;b&#8217;)) {<br /> handler.execute ();<br /> break;<br /> }<br /> }<br /> [/sourcecode]
  </p>

  <p>
    できれば, ひとつメソッドをよんだら, あとは好き勝手に処理されればいい.
  </p>

  <p>
    Amazon で本を注文するときは, ポチったら, あとはコンビニに勝手に届いて入ればいい.
  </p>
</div>

パターン適用

メリット

<div class="outline-text-3" id="text-unnumbered-6">
  <p>
    要求を出す側と, 要求を処理する側の結びつきが弱まる.
  </p>

  <p>
    具体的にいえば, ループを回さなくてすむ.
  </p>
</div>

コード

<div class="outline-text-3" id="text-unnumbered-7">
  [sourcecode language=&#8221;java&#8221; title=&#8221;&#8221;]<br /> public class ChainOfResponsibilitySample {<br /> public static void main (String[] args) {<br /> Handler chain = new A (new B (new C (null)));<br /> chain.handle (&#8216;b&#8217;);<br /> }<br /> }</p> 

  <p>
    abstract class Handler {<br /> private Handler next;
  </p>

  <p>
    public Handler (Handler next) {<br /> this.next = next;<br /> }
  </p>

  <p>
    public void handle (char c) {<br /> if (isMatch (c))<br /> execute ();<br /> else<br /> next.handle (c);<br /> }
  </p>

  <p>
    abstract boolean isMatch (char c);<br /> abstract void execute ();<br /> }
  </p>

  <p>
    class A extends Handler {<br /> public A (Handler next){ super (next); }<br /> boolean isMatch (char c) { return c == &#8216;a&#8217;; }<br /> void execute () { System.out.println ("a hit"); }<br /> }
  </p>

  <p>
    class B extends Handler {<br /> public B (Handler next){ super (next); }<br /> boolean isMatch (char c) { return c == &#8216;b&#8217;; }<br /> void execute () { System.out.println ("b hit"); }<br /> }
  </p>

  <p>
    class C extends Handler {<br /> public C (Handler next){ super (next); }<br /> boolean isMatch (char c) { return c == &#8216;c&#8217;; }<br /> void execute () { System.out.println ("c hit"); }<br /> }<br /> [/sourcecode]
  </p>
</div>

感動のポイント

<div class="outline-text-3" id="text-unnumbered-8">
  <p>
    みよ! このシンプルさを.
  </p>

  <p>
    [sourcecode language=&#8221;java&#8221; title=&#8221;&#8221;]<br /> public static void main (String[] args) {<br /> Handler chain = new A (new B (new C (null)));<br /> chain.handle (&#8216;b&#8217;);<br /> }<br /> [/sourcecode]
  </p>
</div>

こんなの, 関数型の考え方でかけば当たり前だ!

この主張をしたいがために, この記事を書いた.

関数型っぽくかけば, こんなの当たり前の方法.

[sourcecode language=”java” title=””]
public class ChainOfResponsibilityFinctional {
public static void main (String[] args) {

LinkedList chain = new LinkedList();
chain.add (new A ());
chain.add (new B ());
chain.add (new C ());

handle (chain, ‘b’);
}

static void handle (LinkedList chain, char c) {
Handler head = chain.element ();
chain.removeFirst ();
LinkedList tail = chain;
if (head == null)
return;
else {
if (head.isMatch (c)) {
head.execute ();
return;
}
else
handle (tail, c);
}
}
}

abstract class Handler {
public abstract boolean isMatch (char c);
public abstract void execute ();
}

class A extends Handler {
public boolean isMatch (char c) { return c == ‘a’; }
public void execute () { System.out.println ("a hit"); }
}

class B extends Handler {
public boolean isMatch (char c) { return c == ‘b’; }
public void execute () { System.out.println ("b hit"); }
}

class C extends Handler {
public boolean isMatch (char c) { return c == ‘c’; }
public void execute () { System.out.println ("c hit"); }
}
[/sourcecode]

感動のポイント

<div class="outline-text-3" id="text-unnumbered-10">
  <p>
    一行で一応処理できている.
  </p>

  <p>
    [sourcecode language=&#8221;java&#8221; title=&#8221;&#8221;]<br /> handle (chain, &#8216;b&#8217;);<br /> [/sourcecode]
  </p>

  <p>
    末尾再帰を利用している. しかし, あんまりシンプルにかけないな&#x2026;
  </p>

  <p>
    [sourcecode language=&#8221;java&#8221; title=&#8221;&#8221;]<br /> static void handle (LinkedList<Handler> chain, char c) {<br /> Handler head = chain.element ();<br /> chain.removeFirst ();<br /> LinkedList<Handler> tail = chain;<br /> if (head == null)<br /> return;<br /> else {<br /> if (head.isMatch (c)) {<br /> head.execute ();<br /> return;<br /> }<br /> else<br /> handle (tail, c);<br /> }<br /> }<br /> [/sourcecode]
  </p>

  <p>
    ただし, 呼び元で Handler に対してメッセージをおくっているところはかわらないか.
  </p>

  <p>
    Chain of responsibility は, chain のリスト構造のなかに, 責務をカプセル化している.
  </p>
</div>

おわりに

デコレータパターンやコンポジットパターンでも感じるが, Gof のデザインパターンは, 関数型で書いたほうが便利なことを がんばって OOP で書いているように思えるのだが.

関数型デザインパターン

<div class="outline-text-3" id="text-unnumbered-12">
  <p>
    ネットで調べたら, やはり同じことを考えている人はいるようだ.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://sujitpal.blogspot.jp/2013/06/functional-chain-of-responsibility.html">Salmon Run: Functional Chain of Responsibility implementation in Scala</a>
    </li>
  </ul>

  <p>
    以下の二つは関数型パラダイムでのデザインパターンにもなりえると思う.
  </p>

  <ul class="org-ul">
    <li>
      Decorator Pattern
    </li>
    <li>
      Chain of Responsibility Pattern
    </li>
  </ul>
</div>

07 Dec 2014, 12:45

Haskell の xUnit ツール HUnit を試す

はじめに

Haskell でテストコードを書くツールをしらべてみた.

メジャーなものは以下

  • doctest
  • QuickCheck
  • HSpec
  • HUnit

各ツールの特徴

doctest

コメントにテストを書くスタイルのツール.

Python の doctest を haskell に移植したものだとか.

QuickCheck

ランダムなテストデータによって関数の性質をテストする.

xUnit とは異なるコンセプトをもつ.

HSpec

xSpec ライクなテストツール.

Ruby の RSpec にインスパイヤされたらしい.

記法が BDD 的.

HUnit

xUnit ライクなテストツール. JUnit ライク.

HUnit を試す

JUnit になじみがあるので, HUnit を試してみた.

Install

$ cabal install HUnit

Usage

Test.HUnit をインポート.

import Test.HUnit

テスト対象コード

import Data.List
import Data.Char
import Unsafe.Coerce

data Nat = Zero
         | Succ Nat
         deriving Show

natToInteger (Succ n) = natToInteger n + 1
natToInteger Zero = 0

テストコード

tests = TestList
        [ "natToInteger 1" ~: natToInteger Zero ~?= 0
        , "natToInteger 2" ~: natToInteger (Succ Zero) ~?= 1
        , "natToInteger 3" ~: natToInteger (Succ (Succ Zero)) ~?= 2
        ]

テスト実行

runTestTT (テスト関数名) でテスト実行.

$ runTestTT tests
Cases: 3  Tried: 3  Errors: 0  Failures: 0
Counts {cases = 3, tried = 3, errors = 0, failures = 0}

わざと失敗させてみる.

*Main> runTestTT tests
### Failure in: 2:natToInteger 3
expected: 1
 but got: 2
Cases: 3  Tried: 3  Errors: 0  Failures: 1
Counts {cases = 3, tried = 3, errors = 0, failures = 1}

Bookmarks

07 Dec 2014, 11:32

Java におけるポリモーフィズムの整理

はじめに

Haskell で型クラスというものを勉強した.

その延長で, 今までとてもいい加減に理解していた Java のポリモーフィズムについて再度復習した.

なんか, 用語の関係性をすごく曖昧に理解していた気がした.

Polymophism: 多相性

各要素 (定数, 変数, 式, オブジェクト, 関数, メソッドなど) についてそれらが複数の型に属することを許すという性質.

同種のクラスをカテゴリに分類してまとめ, 基本的な動作・設計部分を統一することで, オブジェクトインスタンスの扱いに柔軟性と規律を持たせるための機能.

多相性は 3 つに分類できる.

  • アドホック多相:
  • パラメータ多相:
  • サブタイプ多相:

たとえば Java だと以下に相当する.

  • アドホック多相: オーバーロード
  • パラメータ多相: ジェネリクス
  • サブタイプ多相: 継承, インタフェース

参考:

Polymorphic Type: 多相型

<div class="outline-text-3" id="text-unnumbered-3">
  <p>
    データ構造のコンテナ.
  </p>

  <p>
    データ形式に依存しないコンピュータプログラミング方式をジェネリクス プログラミングという.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://ja.wikipedia.org/wiki/%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AA%E3%83%83%E3%82%AF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0">ジェネリックプログラミング &#8211; Wikipedia</a>
    </li>
  </ul>
</div>

アドホック多相

オブジェクト指向におけるアドホック多相とは, オーバーロードに相当する. 多重定義ともいう.

パラメータ多相

型変数

<div class="outline-text-3" id="text-unnumbered-6">
  <p>
    多相型は宣言されたクラス, 関数に対して, 利用時に具体的な型を与える. これを型変数 (Type variable) という.
  </p>

  <p>
    Java の名前つけルールがあるらしい.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://java.keicode.com/lang/generics-naming.php">名前付けルール &#8211; Java 入門</a>
    </li>
  </ul>
</div>

Generic Type: 総称型

<div class="outline-text-3" id="text-unnumbered-7">
  <p>
    型付けされたプログラミング言語において データ型の定義とそれを参照する式 (型式) の一部にパラメタを許すことによって 類似した構造を持つ複数のデータ型を一括して定義して, それらを選択利用する仕組み.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://ja.wikipedia.org/wiki/%E7%B7%8F%E7%A7%B0%E5%9E%8B">総称型 &#8211; Wikipedia</a>
    </li>
  </ul>

  <p>
    オーバーロード (overload), 継承 (inheritance) と並んでプログラミング言語において ポリモーフィズムを実現するための一つの手段.
  </p>
</div>

言語ごとの実現方法

<div class="outline-text-3" id="text-unnumbered-8">
  <ul class="org-ul">
    <li>
      Java: ジェネリクス, ワイルドカード <ul class="org-ul">
        <li>
          <a href="http://futurismo.biz/archives/2750">Java でのジェネリックスの使い方まとめ | Futurismo</a>
        </li>
      </ul>
    </li>

    <li>
      C++: テンプレート
    </li>
    <li>
      Haskell: <ul class="org-ul">
        <li>
          リスト
        </li>
        <li>
          タプル
        </li>
        <li>
          Either
        </li>
        <li>
          Maybe
        </li>
      </ul>
    </li>
  </ul>
</div>

Subtyping: 派生型

データ型 S が他のデータ型 T と is-a 関係にあるとき, S を T の派生型 (はせいがた, subtype) であるという.

基本型のデータを処理するように作られたプログラムは, その派生型のデータでも正しく処理することができる.

基本型-派生型関係ではリスコフの置換原則 (Liskov Substitution Principle) が成り立つ.

2 つの方法がある

  • インタフェース: 型をグループで分類
  • 継承: 型を階層構造で分類

inheritance: 継承

<div class="outline-text-3" id="text-unnumbered-10">
  <p>
    ほとんどのクラスベースオブジェクト指向言語では, サブクラス (インヘリタンス) が派生型の概念を実現している.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://ja.wikipedia.org/wiki/%E7%B6%99%E6%89%BF_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)">継承 (プログラミング) &#8211; Wikipedia</a>
    </li>
  </ul>
</div>

override: オーバーライド

<div class="outline-text-3" id="text-unnumbered-11">
  <p>
    オブジェクト指向プログラミングにおいてオーバーライド (override) とは, スーパークラスで定義されたメソッドをサブクラスで定義しなおし, 動作を上書きすること.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%89">オーバーライド &#8211; Wikipedia</a>
    </li>
  </ul>
</div>

interface: インタフェース

<div class="outline-text-3" id="text-unnumbered-12">
  <p>
    抽象データ型のメソッド.
  </p>

  <p>
    Object 型を分類し, 同じカテゴリに属するクラスに共通のインターフェイスを取り決める.
  </p>

  <p>
    implements ステートメントは, クラスたちのカテゴリ分類を明確にする方法.
  </p>

  <p>
    変数の型としてカテゴリクラスを指定すると, そのカテゴリを Implements したクラス (つまり, カテゴリに属するクラス) のインスタンスも格納できるようになる.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://homepage1.nifty.com/CavalierLab/lab/vb/clsmdl/polymorphism_02.html">ポリモーフィズムとインターフェイス</a>
    </li>
  </ul>

  <p>
    オブジェクトが, 共通のインターフェイスを実装している場合, 他のオブジェクトに置き換えることができる.
  </p>
</div>

<div id="outline-container-unnumbered-13" class="outline-4">
  <h4 id="unnumbered-13">
    どう分類するか?: 共通性/ 可変性 分析法
  </h4>

  <div class="outline-text-4" id="text-unnumbered-13">
    <p>
      オブジェクト指向のこころより引用.
    </p>

    <ul class="org-ul">
      <li>
        共通性分析:時間が経っても変化しにくい構造を見つけるもの
      </li>
    </ul>

    <p>
      共通性分析によってまとめられた概念を抽象クラスによって表現
    </p>

    <ul class="org-ul">
      <li>
        可変性分析:変化しやすい構造を洗い出すもの
      </li>
    </ul>

    <p>
      可変性分析で得た流動的要素は抽象クラスの派生クラスによって実装される
    </p>

    <p>
      設計手順:
    </p>

    <ul class="org-ul">
      <li>
        (抽象クラス) このクラスが持つ責務をすべて全うするにはどうようなインターフェイスが必要か?
      </li>
      <li>
        (派生クラス) この特定実装の中でどうのようにして与えられた仕様を実装できるのか?
      </li>
      <li>
        共通性: 時がたっても変わらないものを抽象クラスに
      </li>
      <li>
        可変性: 流動的要素を具象クラスに.
      </li>
    </ul>

    <p>
      クラスの集合がもつすべての責務を真っ当するために, インタフェースを用意する.
    </p>

    <p>
      Jim Coplien が提唱. p235 第 15 章から抜粋.
    </p>

    <ul class="org-ul">
      <li>
        <a href="http://www.amazon.co.jp/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%A8%E3%81%A8%E3%82%82%E3%81%AB%E5%AD%A6%E3%81%B6%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AE%E3%81%93%E3%81%93%E3%82%8D-Software-patterns-%E3%82%A2%E3%83%A9%E3%83%B3%E3%83%BB%E3%82%B7%E3%83%A3%E3%83%AD%E3%82%A6%E3%82%A7%E3%82%A4/dp/4894716844">Amazon.co.jp: デザインパターンとともに学ぶオブジェクト指向のこころ (Software patterns series): アラン・シャロウェイ, ジェームズ・ R ・トロット, 村上 雅章: 本</a>
      </li>
    </ul>
  </div>
</div>

型クラス

<div class="outline-text-3" id="text-unnumbered-14">
  <p>
    Haskell の概念.
  </p>

  <ol class="org-ol">
    <li>
      型は値をグループ化する.
    </li>
    <li>
      型クラスは, 型をグループ化する.
    </li>
  </ol>

  <p>
    この説明はわかりやすい.
  </p>

  <ul class="org-ul">
    <li>
      値 < 型 < 型クラス
    </li>
    <li>
      <a href="http://jutememo.blogspot.jp/2009/05/haskell.html">Haskell のモジュールの階層化と, 型クラス &#8211; パラメータ多相とアドホック多相 | すぐに忘れる脳みそのためのメモ</a>
    </li>
  </ul>

  <p>
    型を分類する点でいえば, Java のインタフェースと同義.
  </p>
</div>

おわりに

先月くらいにクラス設計をしていたときに, 会社である怖い人が,

継承とは, オブジェクトを分類するための手段なんだ!

といっていたが, ようやくその意味を理解した気がした.

07 Dec 2014, 04:20

Java で プリミティブ型から byte 型配列へ変換する

はじめに

Java で byte 型を扱う方法を調べてみたのでまとめてみる.

ByteBuffer クラスをつかう

ByteBuffer クラスを利用すると, byte 型に対するいろいろな操作が簡単にできる.

他のプリミティブ型から byte 型配列 に変換

手順は以下.

  1. ByteBuffer.allocate (size) でメモリ獲得.
  2. putXXX メソッドで獲得したメモリに値を挿入
  3. array () で byte 配列に変換
ByteBuffer buffer = ByteBuffer.allocate (arraySize);
buffer = buffer.putXXXX (value)
byte[] bytes = buffer.array ();

Sample

import java.nio.ByteBuffer;

class ByteSample {

    public static void main (String args[]) {
        showBytes (short2Byte ((short) 10));
        showBytes (int2Byte (10));      
        showBytes (int2ByteN (10));
        showBytes (long2Byte (10L));        
    }

    public static byte[] short2Byte (short value) {
        return ByteBuffer.allocate (Short.SIZE/Byte.SIZE).putShort (value).array ();
    }

    public static byte[] int2Byte (int value) {
        return ByteBuffer.allocate (Integer.SIZE/Byte.SIZE).putInt (value).array ();
    }

    public static byte[] long2Byte (long value) {
        return ByteBuffer.allocate (Long.SIZE/Byte.SIZE).putLong (value).array ();
    }

    static void showBytes (byte[] bytes) {
        for (int i=0; i < bytes.length; i++)
            System.out.printf (Integer.toHexString (bytes[i] &0xff));           
        System.out.println ("");
    }
}

出力結果

0a
000a
0000000a

エンディアン対応

ByteBuffer の初期順序は, BIG_ENDIAN.

  • ビッグエンディアン

複数バイトのデータを上位バイトから順番に格納する方式です. 0x1234ABCD を 0x12,0x34,0xAB,0xCD という順番で保存します.

  • リトルエンディアン

複数バイトのデータを下位バイトから順番に格納する方式です. 0x1234ABCD を 0xCD,0xAB,0x34,0x12 という順番で保存します.

リトルエンディアン (ネットワークバイトオーダー) に対応するためには, java.nio.ByteOrder クラスと order メソッドを利用する.

public static byte[] int2ByteN (int value) {
    ByteBuffer byteBuffer = ByteBuffer.allocate (Integer.SIZE/Byte.SIZE);
    byteBuffer.order (ByteOrder.LITTLE_ENDIAN);
    byteBuffer.putInt (value);
    return byteBuffer.array ();
}

Bookmarks

04 Dec 2014, 22:45

動的に機能追加!Java で Decolator パターンを実装してみた

はじめに

Java であるクラスとべつのクラスの差がちょっとしかない場合を仮定する.

どうすれば共通部分を効率よく再利用できるのだろう??

たとえば

こんなとき, どうする??

class A {
    public static void greeding () {
        System.out.println ("Hello");
        System.out.println ("Nice to meet you");
        System.out.println ("Good Bye");
    }
}

class B {
    public static void greeding () {
        System.out.println ("Hello");
        System.out.println ("はじめまして");
        System.out.println ("Good Bye");
    }
}

継承をつかう

こんなときは, 継承によって共通部をスーパークラスにもっていって, 差分だけサブクラスに実装する.

abstract class C {
    public void greeding () {
        System.out.println ("Hello");
        niceToMeetYou ();
        System.out.println ("Good Bye");
    }

    protected abstract void niceToMeetYou ();
}

class A extends C {
    @Override
    protected void niceToMeetYou () {
        System.out.println ("Nice to meet you");        
    }
}

class B extends C {
    @Override
    protected void niceToMeetYou () {
        System.out.println ("はじめまして");  
    }
}

機能追加で破綻

しかし, もう一言なにか言いたくなったときに破綻する. これは, 委譲 (Strategy Pattern) をつかっても同じ.

class D {
    public static void greeding () {
        System.out.println ("Hello");
        System.out.println ("はじめまして");
        System.out.println ("お元気ですか?");
        System.out.println ("Good Bye");
    }
}

Decolator パターンを利用

Decolator パターンを利用すると, 粒粒の機能を動的に組み合わせることができる.

つまり, 以下のような機能を好きな順番で並び替えることができる.

  • System.out.println (“Hello”);
  • System.out.println (“はじめまして”);
  • System.out.println (“お元気ですか?”)
  • System.out.println (“Nice to meet you”); ;
  • System.out.println (“Good Bye”);

機能をオブジェクト化

まずは, 以下の機能を別々のオブジェクトにする. これがデコレータ本体.

  • System.out.println (“Hello”);
  • System.out.println (“はじめまして”);
  • System.out.println (“Nice to meet you”); ;
  • System.out.println (“Good Bye”);
abstract class Component {
    public abstract void operation ();
}

class EndComponent extends Component {
    public abstract void operation (){
        System.out.println ("Good Bye");
    }
}

abstract class Decorator extends Component {
    private Component component;

    public Decorator (Component component) {
        this.component = component;
    }

    public void callOperation () {
        if (component != null)
            component.operation ();
    }
}

class A extends Decorator {
    A (Component component) {
        super (component);
    }

    public void operation {
        System.out.println ("Hello");
    }
}

class B extends Decorator {
    A (Component component) {
        super (component);
    }

    public void operation {
        System.out.println ("Nice to meet you");
    }
}

class C extends Decorator {
    A (Component component) {
        super (component);
    }

    public void operation {
        System.out.println ("はじめまして");
    }
}

Factory でオブジェクト構築

欲しいオブジェクトを好きな順番で構築する.

class Factory {
    public static Component getA () {
        Component component;
        component = new EndComponent ();
        component = new B (component);
        component = new A (component);
        return component;
    }

    public static Component getB () {
        Component component;
        component = new EndComponent ();
        component = new C (component);
        component = new A (component);
        return component;
    }
}

public class DecolatorSample {
    public static void main (String[] args) {
        Factory.getA ().operation ();
        System.out.println ("");
        Factory.getB ().operation ();
    }   
}

関数型言語ならば当たり前??

思ったのは, これって関数型言語で利用される方法なのでは? 関数型言語では, 関数を値として扱うことができる.

関数をリストに詰め込んで, リストを評価すればよい.

というわけで, 無名クラスとリストを用いて実装してみた.

  import java.util.LinkedList;
import java.awt.List;

public class DecolatorWithFunctional {
    public static void main (String[] args) {
        LinkedList<Component> decorators = new LinkedList<>();

        decorators.add (new Component (){
                public void operation () { System.out.println ("Hello"); }
            });
        decorators.add (new Component (){
                public void operation () { System.out.println ("Nice to meet You"); }
            });
        decorators.add (new Component (){
                public void operation () { System.out.println ("Good Bye"); }
            });

        for (Component decolator: decorators){ decolator.operation (); }
    }
}

interface Component {
    public void operation ();
}

関数型のほうが圧倒的にシンプルな気がする.

Enum Strategy Pattern と組み合わせ

前回学んだ, Enum Strategy Pattern と組み合わせる.

public class DecolatorWithFunctional {
    public static void main (String[] args) {
        LinkedList<Component> components = new LinkedList<>();

        components.add (Component.HELLO);
        components.add (Component.NICE);
        components.add (Component.BYE);     

        for (Component component: components){ component.operation (); }
    }
}

enum Component {
    HELLO{ public void operation (){ System.out.println ("Hello"); }},
    NICE { public void operation (){ System.out.println ("Nice to meet you"); }},
    NICE_JA{ public void operation (){ System.out.println ("はじめまして"); }},
    BYE{ public void operation (){ System.out.println ("Bye"); }}; // 

    public abstract void operation ();
}

さらにシンプルになった.

04 Dec 2014, 14:39

IRC クライアントとして Emacs をつかいたい! ERC を試す

はじめに

仕事で IRC をコミュケーションツールとして利用しはじめた.

Emacs のなかで生きているので, IRC も Emacs から接続したい. ということで, Emacs の IRC クライアントを調べる.

IRC とは

Internet Relay Chat の略.インターネットを利用したチャット専用システム.

詳細は, 以下のページ参照.

Emacs 用 IRC クライアント

Emacs Wiki によると, いつくも種類があるようだ.

Emacs にデフォルトで入っていて, ネット上でも情報のおおい ERC を試す.

IRC サーバを用意

なんでもよかったのだが, 有名そうな ngiIRCd をいれる.

設定はひとまず Default 設定で起動.

$ sudo ngircd

Emacs

まずは, Emacs 上で M-x erc で ERC を起動.

ERC の Web マニュアル.

まずは, default の サーバに接続

  • IRC Server: rc.freenode.net
  • port: 6667
  • username: tsu-nera
  • password: はじめは未設定.

つづいて, /join #emacs とタイプすると, emacs のチャットに参加できる.

ログアウトは, M-x erc-quit-server (C-c C-x).

ngircd を利用

自分で用意したサーバでもう少し遊ぶ.

ログイン

  • IRC Server: localhost
  • port: 6667
  • username: tsu-nera
  • password: はじめは未設定.

これで, ログインできる.

設定ファイルにログイン情報を書くとログインが簡単になる.

(setq erc-server "localhost")
(setq erc-port "6667")
(setq erc-nick "tsu-nera")
;; (setq erc-password "")

オートログインもできる. 以下を書いて, M-x erc-opn

(autoload 'erc "erc" "" t)
(defmacro de-erc-connect (command server port nick)
  "Create interactive command `command', for connecting to an IRC server. The
command uses interactive mode if passed an argument."
  (fset command
    `(lambda (arg)
       (interactive "p")
       (if (not (= 1 arg))
           (call-interactively 'erc)
         (erc :server ,server :port ,port :nick ,nick)))))

(de-erc-connect erc-opn "localhost" 6667 "tsu-nera")
#  Channel 接続 /JOIN or /j
/j #test

# 直接話す
/query <nick>

これでも Chanel に接続 できる.

(setq erc-autojoin-channels-alist
      '(("localhost" "#test")))
;;  ("oftc.net" "#bitlbee")))
(erc :server "localhost" :port 6667 :nick "tsu-nera")

ログアウト

# Channel からぬける
/PART

# メッセージを残してサーバをさる
/QUIT msg
;; Kill buffers for channels after /part
(setq erc-kill-buffer-on-part t)

Highlight

(require 'erc-match)
(setq erc-keywords '("tsu-nera"))

erc-highlight-nicknames

ニックネームをハイライト

(and
  (require 'erc-highlight-nicknames)
  (add-to-list 'erc-modules 'highlight-nicknames)
  (erc-update-modules))

erc-hl-nicks

erc-highlight-nicknames の改良版か?

(require 'erc-hl-nicks)

nerc-nick-notify

ニックネームが呼ばれたら反応する.

(autoload 'erc-nick-notify-mode "erc-nick-notify"
  "Minor mode that calls `erc-nick-notify-cmd' when his nick gets
mentioned in an erc channel" t)
(eval-after-load 'erc '(erc-nick-notify-mode t))

Encoding

こんな感じか?

;; UTF-8
(setq  erc-server-coding-system '(utf-8 . utf-8))

;; Shift-JIS
(setq erc-server-coding-system に (iso-2022-jp . iso-2022-jp))

Color

ダークにはデフォルトのいろがみずらい

(add-to-list 'custom-theme-load-path "~/.emacs.d/elisp")
(load-theme 'blue-erc t t)
(enable-theme 'blue-erc)

Bookmarks

IRC について.

Windows で一番有名? な IRC クライアント.

IRC Client の比較.

ERC

Emacs にデフォルトで入っている.

Riece

Cabon Emacs にデフォルトで入っている.リースと読む.

Circe

けっこう最近 (2013) にでてきたやつ. 開発は盛ん.

weechat.el

最近でてきた CUI 用 IRC Client, weechat を Emacs から利用する.

ngircd

01 Dec 2014, 14:04

Effective Java を読んだ.エレガントな手法に感動した.

はじめに

仕事で Java をつかうようになった.

といっても, まだ 8 時間くらいしかプログラミングしてないんだけど・・・.

ここ一か月, 怒涛のようにブログの記事を書いているけれども, そのほとんどが Java に関する記事だ.

たとえば…

それは, 元ネタはほとんど Effective Java だったりする.

2 週間ちかくかかったけれども, ようやく読みきったので感想を書く.

内容の紹介

紹介といっても, あまりに有名な本なので紹介するまでもないかも..

Java をつかうプログラマ必読の書

と, よくネットで見かける.自分も, この誘い文句に惹かれて本を手に取った.

第 2 版 は Java 6 の仕様にそって, Java を使う上での有効なテクニックが 78 項目, 順に紹介されていく.

題名のとおり, Effective な Java 文法の使い方のカタログ. よいとされる Java の書き方が, なぜそうするべきなのか説明される.

  • 第 2 章 オブジェクトの生成と消滅 (項目 1 〜 項目 7)
  • 第 3 章 すべてのオブジェクトに共通のメソッド (項目 8 〜 項目 12)
  • 第 4 章 クラスとインタフェース (項目 13 〜項目 22)
  • 第 5 章 ジェネリックス (項目 23 〜 29)
  • 第 6 章 enum とアノテーション (項目 30 〜 項目 37)
  • 第 7 章 メソッド (項目 38 〜 項目 44)
  • 第 8 章 プログラミング一般 (項目 45 〜 項目 56)
  • 第 9 章 例外 (項目 57 〜 項目 65)
  • 第 10 章 並行性 (項目 66 〜 項目 73)
  • 第 11 章 シリアライズ (項目 74 〜 項目 78)

順番に読む必要はないので, 目次をみて気になったところからつまみ読みできる.

感想

Elegant java

まず, この本に乗っている手法はとてもエレガントだ.

関心して, かつ興奮することが毎日体験できる. 思わず写経して, 記事にしてしまうほど, 感動するのだ!

どんな風に感動したかは, 過去記事に譲る.

Elegant Java というタイトルでも十分通用する.

あたりまえのようにデザインパターンがでてくる

オブジェクト指向言語における, 美しいパターンが各ページにちりばめられている.

Gof のデザインパターンというものが, オブジェクト指向でよく利用されるパターンのカタログならば, Effective な手法と Gof のパターンがかぶってしまうことは当たり前.

出てきたものを, 思いつくままに抜粋.

  • ファクトリーメソッド 項目 1
  • ビルダー 項目 2
  • シングルトン 項目 3
  • デコレータ 項目 16
  • ブリッジ 項目 18
  • ストラテジ 項目 21
  • アダプタ 項目 22
  • オブザーバ 項目 67
  • フライウェイト 項目 71

継承をやたら敵対視

とくに印象的だったのが, 以下の章だ.

  • 第 4 章 クラスとインタフェース (項目 13 〜項目 22)
  • 第 6 章 enum とアノテーション (項目 30 〜 項目 37)

Enum は別記事に譲るとして, ここではインタフェースについてのコメントを抜粋.

  • 継承よりもコンポジションを選ぶ 継承は不必要なメソッドを公開する. つまり, 継承はカプセル化を破る.

  • 継承をつかうならば設計を文書化する, でなければ禁止だ.

  • 抽象クラスよりもインタフェースを選ぶ 実装の観点では,

    • 抽象クラスはメソッドに対する実装を含むことを許されている.
    • インタフェースはメソッドに対する実装を含むことを許されていない.

    機能の観点では, - 抽象クラスはある機能の実装を強制する. - インタフェースは任意の機能を混ぜ合わせる.

    階層化の観点では, - 抽象クラスは物事を階層化することに優れる. - インタフェースは階層を持たないものをまとめることに優れる.

  • インタフェースは, 階層を持たない型システムを構築する.

おわりに

とてもよい読後感だ.

いいエンディングの映画をみたように, ここに掲載されている手法の美しさに心を打たれた.

各項目が細かく分類されているのもよい. Java での実装に困ったとき, 折に触れて読み返そうと思った.

BookMarks

30 Nov 2014, 12:21

Effective Java にのっている エレガントな Enum の使い方メモ

はじめに

Effective Java には毎回驚かされる.

Enum とは

プログラマが選んだ各々の識別子をそのまま有限集合として持つ抽象データ型.

番号を持たないカテゴリ変数. 一意の文字定数.

実行時には, 番号が振られることが覆いが, 言語によっては番号はプログラマに見えないこともある.

int enum パターン

名前つき int 定数のグループを宣言すること.バッドノウハウ.

[sourcecode language=”java” title=””]
public static final int FOO = 0;
public static final int BAR = 1;
[/sourcecode]

  • コンパイラによる型検査の恩恵を受けることができない.
  • 同じ名前がついたものを名前空間で区別することができない.
  • 変更により再コンパイルが必要.
  • 表示可能な文字列へ変換する方法かない.
  • int と enum では実効速度はそれほどかわらない.

定数固有メソッド実装 (constant-specific method implementation)

enum 定数に対して振る舞いを関連付けるための方法.

パターン適用前.

[sourcecode language=”java” title=””]
public enum Operation {
PLUS, MINUS;

double apply (double x, double y) {
switch (this) {
case PLUS: return x + y;
case MINUS: return x – y;
}
throw new AssertionError () ("Unknown op:" + this);
}
}
[/sourcecode]

パターン適用後. enum 型で抽象メソッドを宣言して, 定数固有クラス本体で, 定数ごとに具象メソッドで その抽象メソッドをオーバーライド.

switch 文を排除するので, エレガント!! 抽象メソッドによって実装をカプセル化.

[sourcecode language=”java” title=””]
public enum Operation {
PLUS { double apply (double x, double y) {return x + y;} },
MINUS { double apply (double x, double y) {return x – y;} };

abstract double apply (double x, double y);
}
[/sourcecode]

定数固有クラス

さらに, 定数固有データと実装を組み合わせることで, 強力な表現力を.

[sourcecode language=”java” title=””]
public enum Operation {
PLUS ("+") { double apply (double x, double y) {return x + y;} },
MINUS ("-") { double apply (double x, double y) {return x – y;} };

private final String symbol;
Operation (String symbol) { this.symbol = symbol; }
@Override public String toString () { return symbol; }

abstract double apply (double x, double y);
}
[/sourcecode]

Enum の toString は定数表現は 文字列へ変換することもできる.

戦略 Enum (Strategy Enum)

抽象メソッドをクラスに変更して外部から与えてやるようにすれば, これはいわゆる Strategy Pattern だ.

評価戦略を外部から与えて, Operation は委譲で評価をする.

[sourcecode language=”java” title=””]
public enum Operation {
PLUS (EvaluateType.PLUS), MINUS (EvaluateType.MINUS);

private final EvaluateType type;

Operation (EvaluateType type) {
this.type = type;
}

double apply (double x, double y) {
return type.apply (x, y);
}

// Strategy Enum Type
private enum EvaluateType {
PLUS { double apply (double x, double y) {return x + y;} },
MINUS { double apply (double x, double y) {return x – y;} };

abstract double apply (double x, double y);
}
}
[/sourcecode]

enum 定数と値の関連付けに ordinal をつかわないこと

enum と関連付けられた int 値を取得する メソッドとして ordinal メソッドがある.

これを定数と値を関連付けるときには, 使わない. なぜなら, コードの修正で, 振られる番号が変わるから.

[sourcecode language=”java” title=””]
public enum Number {
ONE, TWE;
public int getNumber{ return ordinal () + 1; }
}
[/sourcecode]

代わりにインスタンスフィールドを利用すればよい.

[sourcecode language=”java” title=””]
public enum Number {
ONE (1), TWE (2);
private final int number;
Number (int number) { this.number = number;}
public int getNumber{ return number; }
}
[/sourcecode]

集合と集合の対応づけに序数インデックス (配列) をつかわない

2 つの集合を対応付けるときには, 配列をつかうよりもいい方法がある.

それは, EnumMap. EnumMap は内部実装は配列でされているものの, インデックスを意識する必要がないというメリットがある.

配列をインデックスするために序数を使用することが適切であることはほ とんどない.代わりに, EnumMap を使用すること.

関連が多次元ならば, EnumMap<…, EnumMap<…>> というように連なっていく.

[sourcecode language=”java” title=””]
Map> herbsByType =
new EnumMap>(Herb.Type.class);
for (Herb.Type t : Herb.Type.values ())
herbsByType.put (t, new HashSet());
for (herb h: garden)
herbsBytpe.get (h.type).add (h);
[/sourcecode]

Enum シングルトンパターン

Enum を利用して, シングルトンパターンをする方法.

[sourcecode language=”java” title=””]
class SampleSingleton {
static public enum EnumUtil {
INSTANCE;

public static int plus (int x, int y) { return x + y; }
public static int minus (int x, int y) { return x – y; }
}

public static void main (String[] args) {
System.out.println (EnumUtil.INSTANCE.plus (1,1));
System.out.println (EnumUtil.INSTANCE.minus (2,1));
}
}
[/sourcecode]

29 Nov 2014, 10:47

Haskell で Hello World! しようとしたらモナドでドナドナした

file:./../img/IMG_3895.JPG

はじめに

最近発売された, Haskell 本を買ってみた.

どんな言語でも, はじめは Hello, World を出力するところからはじめる.

Haskell で Hello, World をするためには, ノマドというものを理解しない といけない. この本では p267 に書いてある. なんと険しき Hello, World…

モナドとは

とりあえず理解したことを自分の言葉でメモ. あまりわかっていない. モナドとノマドとドナドナの違いがわからない.

モナドとは, 純粋関数と副作用を共存さ競るためのしくみ.

純粋関数

同じ引数を渡す限り, どのような順番で何度呼んでも同じ結果が返るような関数.

副作用

ある機能がコンピュータの (論理的な) 状態を変化させ, それ以降で得られる結果に影響を与えること.

  • 状態を参照することで出力が変化すること
  • 状態に変化を与えることで出力が変化すること

例としては,

  • 破壊的代入
  • I/O 制御 (write/print 等)

wikipedia

ちなみに, wikipedia は,

プログラムとはクライスリ圏の射である , という要請から合成規則としてクライスリトリプル (Kleisli triple) というモナドと等価なものが用いられる.

ショボーン. 線形代数の単位を落としたオレをなめるなよ!

不条理な世の中と清められた世界

そう, Hello, World とは純粋で汚れのない pure な世界を汚す副作用.

そして, 純粋関数で構築されたプログラムは, 論理で構築された絶対的な世界!

絶対的な真理として存在する数学や音楽の秩序が美しさを持つように, 純粋関数によって構築された秩序は, それ自体が美しいのだ!

Hello, World!

コードを以下に示す.

main :: IO ()
main = putStrLn "Hello, World!"

IO という部分は, IO モナドと呼ばれる.

putStrLn は String を受け取り, IO を返す.

Prelude> :t putStrLn
putStrLn :: String -> IO ()

Bookmarks

Ruby での解説:

Haskell におけるモナドの解説ページ: