クラなんとか or くらなんとか or cla なんとかの日記

2011-11-14

ギークバーに行ってきた

今回は,JVM について調べていた.

hello.j

.class public hello
.super java/lang/Object

.method public <init>()V
   aload_0
   invokenonvirtual java/lang/Object/<init>()V
   return
.end method

.method public static main([Ljava/lang/String;)V
   .limit stack 2
   getstatic java/lang/System/out Ljava/io/PrintStream;
   ldc "Hello, World!"
   invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
   return
.end method

ちょっと真面目に書くとこんな感じ

public class hello extends java.lang.Object {
    public void hello() {
        super();
    }

    public static void main(java.lang.String[] args) {
        java.io.PrintStream p = java.lang.System.out;
        java.lang.String s = "Hello, World!";
        p.println(s);
    }
}


データタイプ

  • プリミティブタイプ
  • リファレンスタイプ

ご参考

2010-02-20

Java 版チャーチ数を書いてみた(改)

ということで,以前書いたJava 版チャーチ数を更新しました.

以前のバージョンだと戻り値の型がjava.lang.Integer 決め打ちだったのが

気になっていたので,それをtype variable にして外に追い出しました.

簡単な説明

ついでに,以下の4つのパターンでテストを書いてみました.

  • Test::More(Perl)
  • JUnit(Java)
  • ScalaTest(Scala)
  • test-is(Clojure)

気付いたこととしては,Clojure は,型がゆるい所為か

Java ソースに型変数部分を導入しても型変数部分を変更する必要が無かった.

Clojure 版はソースも短い.

Scala は,型LOVE なら,記述力も高いし気持いい.

とあいえ,型変数の<> を [] で書く.型を後に書くとか,

Java と混ぜて書くのは訳わからんくなりそう.

Clojure だと,違うところは違い,同じところは同じなので,その辺があまり気にならない気がした.*1

調べ足りないこと,Java でクロージャを作ろうとすると final が必要になるのは何故?

参考

スーパーpre 記法が,Clojure に対応していて良かった.-> d:id:hatenadiary:20100219:1266571864

ちぇりお!

以下ソース


Main.java

class Main {
    public static void main(String[] args) {
        Church zero = Church.ZERO;
        Church one = zero.inc();
        Church two = one.inc();
        Church three = one.plus(two);

        F<Integer> to_i = new F<Integer>() {
                public Integer proc(Integer x) {
                    return Integer.valueOf(x.intValue() + 1);
                }
            };

        Integer number_zero = new Integer(0);

        System.out.println(zero.proc(to_i).proc(number_zero));
        System.out.println(one.proc(to_i).proc(number_zero));
        System.out.println(two.proc(to_i).proc(number_zero));
        System.out.println(three.proc(to_i).proc(number_zero));
    }
}

F.java

public interface F<T> {
    public T proc(T x);
}

Church.java

// proc :: (a -> a) -> a -> a
// (a -> a)         is F (interface)
// proc F :: a -> a is F
// (a)              is T (anonymous type)
abstract public class Church {
    abstract public <T> F<T> proc(F<T> f);

    public static Church ZERO = new Church() {
            public <T> F<T> proc(F<T> f) {
                return new F<T>() {
                    public T proc(T x) {
                        return x;
                    }
                };
            }
        };

    public Church inc() {
        return Church.inc(this);
    }

    public Church plus(final Church n) {
        return Church.plus(this, n);
    }

    public static Church inc(final Church n) {
        return new Church() {
            public <T> F<T> proc(final F<T> f) {
                return new F<T>() {
                    public T proc(T x) {
                        return f.proc(n.proc(f).proc(x));
                    }
                };
            }
        };
    }

    public static Church plus(final Church m, final Church n) {
        return new Church() {
            public <T> F<T> proc(final F<T> f) {
                return new F<T>() {
                    public T proc(T x) {
                        return n.proc(f).proc(m.proc(f).proc(x));
                    }
                };
            }
        };
    }
}

ChurchTest.java - JUnit 版テスト

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.runner.JUnitCore;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

public class ChurchTest {
    private Church zero = null;
    private Church one = null;
    private Church two = null;
    private Church three = null;
    private F<Integer> to_i = null;
    private Integer i_zero = null;

    @Before
    public void before() {
        this.zero = Church.ZERO;
        this.to_i = new F<Integer>() {
            public Integer proc(Integer x) {
                return Integer.valueOf(x.intValue() + 1);
            }
        };
        this.one = zero.inc();
        this.two = one.inc();
        this.three = one.plus(two);
        this.i_zero = new Integer(0);
    }

    @After
    public void after() {
        this.zero = null;
        this.one = null;
        this.two = null;
        this.three = null;
        this.to_i = null;
        this.i_zero = null;
    }

    @Test
    public void testToI() {
        assertThat(this.to_i.proc(i_zero), is(new Integer(1)));
    }

    @Test
    public void testZero() {
        assertThat(to_i(this.zero), is(0));
    }

    @Test
    public void testOne() {
        assertThat(to_i(this.one), is(1));
    }

    @Test
    public void testTwo() {
        assertThat(to_i(this.two), is(2));
    }

    @Test
    public void testThree() {
        assertThat(to_i(this.three), is(3));
    }

    int to_i(Church n) {
        return n.proc(this.to_i).proc(this.i_zero).intValue();
    }

    public static void main(String[] args) {
        JUnitCore.main(ChurchTest.class.getName());
    }
}

ChurchTestSuite.scala - ScalaTest 版

import org.scalatest.FunSuite
 
class ChurchTestSuite extends FunSuite {
  val zero = Church.ZERO;
  val one = zero.inc;
  val two = one.inc;
  val three = two.plus(one); // 2 + 1
  val to_i = new F[java.lang.Integer] {
    def proc(x : java.lang.Integer) : java.lang.Integer = {
      java.lang.Integer.valueOf(x.intValue + 1)
    }
  }

  test("inc is increment") {
    assert(to_i.proc(0) === 1)
  }
 
  test("zero:Church convert to zero:Num (Church.ZERO)") {
    assert(c_to_i(zero) === 0)
  }

  test("one:Church convert to one:Num (Church.inc)") {
    assert(c_to_i(one) === 1)
  }

  test("two:Church convert to two:Num (Church.inc for incremented)") {
    assert(c_to_i(two) === 2)
  }

  test("three:Church convert to three:Num (Church.plus)") {
    assert(c_to_i(three) === 3)
  }

  // helper method
  def c_to_i(n : Church) : Int = {
    n.proc(to_i).proc(0).intValue
  }
}

test.clj - test-is 版

(ns test
  (:import F Church)
  (:use clojure.contrib.test-is))

(def to_i (proxy [F] [] (proc [x] (+ x 1))))
(def zero (Church/ZERO))
(def one (. zero inc))
(def two (. one inc))
(def three (. one (plus two)))

(defn c_to_i [n]
  (.. n (proc to_i) (proc 0)))

(deftest test-to_i
  (is (= 1 (. to_i (proc 0)))))

(deftest test-zero-for-static_value
  (is (= 0 (c_to_i zero))))

(deftest test-one-for-inc
  (is (= 1 (c_to_i one))))

(deftest test-two-for-inc-with-incremented-value
  (is (= 2 (c_to_i two))))

(deftest test-three-for-plus
  (is (= 3 (c_to_i three))))

(run-tests)

*1:単にScala に慣れていない所為とも言う

2010-02-18

scala のインタラクティブでつまづき中(Java のクラスをScala で使う) - 終了

Java のクラスをScala から呼ぼうとしているんだけど,

インタラクティブからだと怒られる.

2010/02/19 追記

public class にしてないだけでした.Java 慣れてなすぎ > 自分

gist の方修正しました.

AA.java

class AA {
    public int func(int x) {
        return x + 2;
    }
}

test.scala

val aa = new AA;
println(aa.func(10))

実行

$ javac AA.java
$ scala test.scala
12
$ echo :l test.scala | scala
Welcome to Scala version 2.7.7.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_17).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :l test.scala
Loading test.scala...
java.lang.IllegalAccessError: tried to access class AA from class 
        at .<init>(<console>:4)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:3)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.re...<console>:5: error: not found: value aa
       println(aa.func(10))
               ^

scala>
$

まぁ,インタラクティブからやんなきゃいいんだけどね.

何かパスみたいなの指定するのが吉ですか?

ちぇりお!

2010-02-17

Java でチャーチ数を書いてみた(途中)

ということで,Java を勉強し直すということにして,チャーチ数を書いてみた.

色々納得がいってないので後で書き直す.

interface F {
    public Integer proc(Integer x);
}

abstract class Church {
    abstract public F proc(F f);

    public static Church ZERO = new Church() {
            public F proc(F f) {
                return new F() {
                    public Integer proc(Integer x) {
                        return x;
                    }
                };
            }
        };

    public Church inc() {
        return Church.inc(this);
    }

    public Church plus(final Church n) {
        return Church.plus(this, n);
    }

    public static Church inc(final Church n) {
        return new Church() {
            public F proc(final F f) {
                return new F() {
                    public Integer proc(Integer x) {
                        return f.proc(n.proc(f).proc(x));
                    }
                };
            }
        };
    }

    public static Church plus(final Church m, final Church n) {
        return new Church() {
            public F proc(final F f) {
                return new F() {
                    public Integer proc(Integer x) {
                        return n.proc(f).proc(m.proc(f).proc(x));
                    }
                };
            }
        };
    }
}
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.runner.JUnitCore;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

public class ChurchTest {
    private Church zero = null;
    private Church one = null;
    private Church two = null;
    private Church three = null;
    private F to_i = null;
    private Integer i_zero = null;

    @Before
    public void before() {
        this.zero = Church.ZERO;
        this.to_i = new F() {
            public Integer proc(Integer x) {
                return Integer.valueOf(x.intValue() + 1);
            }
        };
        this.one = zero.inc();
        this.two = one.inc();
        this.three = one.plus(two);
        this.i_zero = new Integer(0);
    }

    @After
    public void after() {
        this.zero = null;
        this.one = null;
        this.two = null;
        this.three = null;
        this.to_i = null;
        this.i_zero = null;
    }

    @Test
    public void testToI() {
        assertThat(this.to_i.proc(i_zero), is(new Integer(1)));
    }

    @Test
    public void testZero() {
        assertThat(to_i(this.zero), is(0));
    }

    @Test
    public void testOne() {
        assertThat(to_i(this.one), is(1));
    }

    @Test
    public void testTwo() {
        assertThat(to_i(this.two), is(2));
    }

    @Test
    public void testThree() {
        assertThat(to_i(this.three), is(3));
    }

    int to_i(Church n) {
        return n.proc(this.to_i).proc(this.i_zero).intValue();
    }

    public static void main(String[] args) {
        JUnitCore.main(ChurchTest.class.getName());
    }
}

2010-02-16

Java での型変数とか

Mixi の「Java の課題丸投げ」コミュで,「オブジェクト指向」トピって立ってて,

回答者は真面目に応えていたけど,それはそれで面白くなかったので,

自分でも書いてみた.

内容はこんな感じ,適宜編集してある.

課題1

ラーメンをオブジェクト指向で表現。
3種類程度のラーメンが表現できるようにする。
- フィールド     ... (1)
- メソッド       ... (2)
- オーバーロード ... (3)
- オーバーライド ... (4)
- カプセル化(他クラスからのアクセスはgetメソッドとsetメソッドのみ) ... (5)
が確実に表現されていること。

実行は以下のクラスから呼び出される
  class RamenExample{
      public static void main(String [] args){
          Ramen shouyuRamen = new Ramen("しょうゆ");
          Ramen misoRamen = new Ramen("みそ");
          Ramen shioRamen = new Ramen("しお");
      }
  }

また、以下のクラスは生成が条件
  class Ramen {  }
  class Utsuwa {  }
  class Soup {  }
  class Pasta {  }
  class Topping {  }

結果としては,うん.まぁ.あんまり面白く書けなかった.

とあいえ,Java の型変数の書き方がわかったので良しとしよう.

import java.util.ArrayList;
import java.util.LinkedList;

// 条件のクラス

class Ramen {

    // メソッド(Ramen, toString, ...)
    Ramen(String type) {
        utsuwa = new Utsuwa();
        pasta = new Pasta();
        topping.add(new Topping(Topping.Type.チャーシュー));
        topping.add(new Topping(Topping.Type.卵));
        topping.add(new Topping(Topping.Type.ネギ));

        try {
            soup = new Soup(type);
        } catch (IllegalArgumentException e) {
            // 存在しないラーメンを頼まれたら,デフォルトにしちゃうよ
            soup = new Soup();
        }

        System.out.println(this);
    }

    public String toString() {
        LinkedList<Topping> list = new LinkedList<Topping>(topping);
        return
              "器:         " + utsuwa + "\n"
            + "スープ:     " + soup + "\n"
            + "麺:         " + pasta + "\n"
            + "トッピング: " + CollectionUtil.join(list, ", ");
    }

    // フィールド(utsuwa, soup, pasta, topping)
    Utsuwa utsuwa;
    Soup soup;
    Pasta pasta;
    ArrayList<Topping> topping = new ArrayList<Topping>();
}

class Utsuwa {
    enum Type {
        ラーメンどんぶり
    }
    Utsuwa() {
        this.type = Type.ラーメンどんぶり;
    }
    public String toString() {
        return type.name();
    }
    Type type;
}

class Soup {
    enum Type {
        しょうゆ, 
            みそ,
            しお
            }

    // オーバーロード(Soup)
    Soup() {
        this(Type.しょうゆ);
    }
    Soup(String type) throws IllegalArgumentException {
        this(Type.valueOf(type));
    }
    Soup(Type type) {
        this.type = type;
    }

    public String toString() {
        return type.name();
    }
    Type type;
}

class Pasta {
    enum Type {
        中太麺
    }
    Pasta() {
        this.type = Type.中太麺;
    }
    public String toString() {
        return type.name();
    }
    Type type;
}

class Topping {
    enum Type {
        チャーシュー,
            卵,
            ネギ,
    }
    Topping(Type type) {
        this.type = type;
    }
    public String toString() {
        return type.name();
    }
    Type type;
}

// ここから補助クラス,インターフェイス

class CollectionUtil {

    public static <T> String join(LinkedList<T> list, final String delim) {
        String first = list.removeFirst() + "";
        return foldLeft(list, first, new Procedure<T, String>() {
                // オーバーライド(apply)
                @Override
                public String apply(String init, T element) {
                    return init + delim + element;
                }
            });
    }

    public static <A, B> B foldLeft(LinkedList<A> list, B init, Procedure<A, B> proc) {
        if (list.size() == 0) {
            return init;
        } else {
            B next = proc.apply(init, list.removeFirst());
            return foldLeft(list, next, proc);
        }
    }
}
interface Procedure<A, B> {
    public B apply(B init, A element);
}

ソース全部