2011年11月9日水曜日

Scalaで文字列中の各出現文字をカウントする

Mapを使ったソースを書いてみようと思ってネタを考えてウダウダした結果、タイトルのようなソースが出来上がりました。
ついでなので関数の部分適用なども使ってみました。

下記サンプルソースに盛り込まれている要素は、
  • Map(mutable)
  • 関数の部分適用
  • 関数のオーバロード
になります。

では早速サンプルソースです。


object CharacterCount {     // scala.collection.mutableをインポートしておけば、mutable.Mapの宣言が短くできる     // インポート無 → cala.collection.mutable.Map[Char, Int]()     // インポート有 → mutableMap[Char, Int]()     import scala.collection.mutable
    /**      * 指定された文字列中に出現する各文字をカウントし、Mapに格納する      * @param text 出現する文字をカウントしたい文字列      * @param limit 出現回数がlimit回以上の文字のみ返す      * @return text中、limit回以上出現した文字と出現回数を格納したMap      */     def getMapWithLimit(text:String, limit:Int):mutable.Map[Char,Int] = {         count(text).filter( (kv) => kv._2 >= limit )     }     /**      * getMapWithLimitの部分適用      * getMapWithLimit(text, 1)と指定したのと同じ      * @param text 出現する文字をカウントしたい文字列      * @return text中、1回以上出現した文字と出現回数を格納したMap      */     def getMap = getMapWithLimit(_:String, 1)     /**      * 部分適用したgetMapをオーバロードしたもの      * getMapWithLimitと全く同じ      * @param text 出現する文字をカウントしたい文字列      * @param limit 出現回数がlimit回以上の文字のみ返す      * @return text中、limit回以上出現した文字と出現回数を格納したMap      */     def getMap(text:String, limit:Int):mutable.Map[Char,Int] = {         getMapWithLimit(text, limit)     }     /**      * 指定された文字列に出現する各文字をカウントし、Mapに格納して返す      * @param text 出現する文字をカウントしたい文字列      * @return text中の各文字と出現回数を格納したMap      */     private def count(text:String):mutable.Map[Char, Int] = {         val map = mutable.Map[Char, Int]()         text.foreach ( (char) => {             // MapのgetOrElseは、第1引数に指定したキーが存在しない場合に、第2引数の値を返します             val count = map.getOrElse( char, 0 )             map.update( char, count+1 )         })         map     }     // 関数の部分適用部分は、以下のようにしても結果は同じ     //def getMap(text:String) = { getMapWithLimit(text, 1) } }

getMap関数(メソッド?)を使うと、文字列中の各文字をキーとし、値に出現回数が格納されたmutable.Mapのインスタンスが返されます。
REPLから試すと以下のとおりです。


scala> val text = "となりのきゃくはよくかきくうきゃくだ。"
text: java.lang.String = となりのきゃくはよくかきくうきゃくだ。

// CharacterCountって打つのが面倒くさいのでccという変数に格納
scala> val cc = CharacterCount
cc: CharacterCount.type = CharacterCount$@2e5facbd

// 出現回数か1回以上の文字を取得(つまり全文字)
scala> cc.getMap(text)
res0: scala.collection.mutable.Map[Char,Int] = Map(の -> 1, か -> 1, う -> 1, く -> 4, ゃ -> 2, と -> 1, き -> 3, な -> 1, は -> 1, よ -> 1, 。 -> 1, り -> 1, だ -> 1)

// 出現回数が3回以上の文字のみ取得
scala> cc.getMap(text, 3)
res1: scala.collection.mutable.Map[Char,Int] = Map(く -> 4, き -> 3)


map.getOrElseに関して、これがScalaの目玉機能の一つであるOption型(Some型とNone型がある)に直結する機能です。JavaであればExceptionが発生しそうなところ、Noneが返されるので結果的に処理が無視される or 指定した処理が実行されることになります。 このOptionに関してはまだ勉強中なのでまた今度サンプルソースを書いてみたいと思っています。

これぐらいのプログラムであれば態々戻り値の型を書かなくても把握できるしScalaが理解できているならコメントもいらないくらいだと思います。(私は理解できていないのでコメントを書きました)
コメントと型の記述を省いて型推論に頼るとこんなにスッキリしました。


object CharacterCount2 {

    def getMapWithLimit(text:String, limit:Int) = {
        count(text).filter( (kv) => kv._2 >= limit )
    }

    def getMap = getMapWithLimit(_:String, 1)

    def getMap(text:String, limit:Int) = {
        getMapWithLimit(text, limit)
    }

    private def count(text:String) = {
        val map = scala.collection.mutable.Map[Char, Int]()
        text.foreach ( (char) => {
            map.update( char, map.getOrElse(char,0)+1 )
        })
        map
    }
}


今回は各文字でカウントアップしましたが、ちょっと工夫すれば単語単位でカウントすることも可能だと思います。
英語やドイツ語であればスペースで文章を区切ってしまえば自動的に単語単位になるので、うまいこと考えれば今年生まれた新語一覧なんかも作れるのかな~と思ったりしてます。

2011年11月3日木曜日

ドイツの歴史(超概要)


ドイツの歴史をざっくりまとめてみました。
本当にざっくりなので後々修正予定です。
しかし学生のころと違って興味を持って歴史を調べると楽しいですね~
なお、この超概要はこのサイト様を参考にさせていただいております。
参考というより、元々とても綺麗に整理されていたものをさらに私が理解できるレベルに箇条書きにした感じです。


1.ガリア遠征(BC58~BC51)などでゲルマン人は傭兵や農民としてローマ帝国に溶け込む


2.ゲルマン民族の大移動を経て、乱立した各地の王国をフランク王国が統一


3.843年のヴェルダン条約によって、分割されたうちの1つである東フランク王国(843年~962年)が現在のドイツの原型となった


4.東フランク王国の国王オットー1世は962年にアウグストゥス(古代ローマ帝国皇帝の称号)を得て、神聖ローマ帝国(962年~1806年)と呼ばれる緩やかな連合体を形成した(長い!)


5.中世におけるドイツには国家としての統一や民族意識はほとんどなく、各地に領邦国家が分立した。これが現在に続く連邦主義の基盤となっているといえる


6.宗教改革では、新旧両教に分かれて互いに争い、三十年戦争ではドイツ全土が徹底的に破壊され、1600万人いたドイツの人口が600万人に減少したといわれる


7.1701年に、北部の領邦君主ホーエンツォレルン家がプロイセン王国(1701年~1918年)を形成した


8.1806年まで神聖ローマ皇帝位を世襲していた「大ドイツ主義」派のハプスブルク家、「小ドイツ主義」派のホーエンツォレルン家とドイツ統一の役割を争った。


9.ナポレオンによる侵略を経て、民族意識と統一国家への志向を強め、19世紀前半にはプロイセンに主導的な役割を期待する気運が高まった。神聖ローマ帝国はナポレオンにの攻勢に屈して解体されハプスブルク家のフランツ2世が1806年に退位した。神聖ローマ帝国の滅亡である。


10.1871年、プロイセン国王ヴィルヘルム1世の戴冠によってドイツはドイツ系オーストリアを除く、小ドイツとしてのドイツ国(ドイツ帝国(1871年~1918年))として統一され、ベルリンを首都とした。(ちなみにこの戴冠式はパリのヴェルサイユ宮殿で行われた)


11.1918年、第1次世界大戦の敗北によって共和制(1919年~1933年)に移行。しかし、ヴァイマル共和制は小党乱立により政局は不安定で、第1次世界大戦後の賠償などもあり、ドイツ国内は驚異的なインフレとなる


12.1933年に、インフレなどを経て、アドルフ・ヒトラー率いるナチス党(国家社会主義ドイツ労働者党)が国民からの支持を受け、政権を握る


13.1939年9月に隣国ポーランドを攻略し、第2次世界大戦が勃発


14.第2次世界大戦に敗北し、オーデル・ナイセ線以東やシュレジェン地域を領土として喪失。さらに、アメリカ、イギリス、フランス、ソビエト連邦の四か国に分割統治される。


15.1949年、盆を暫定的な首都とするドイツ連邦共和国(西ドイツ)と、ベルリンの東部地区(東ベルリン)を首都とするドイツ民主共和国(東ドイツ)に分裂した。


16.1989年ソビエト連邦のペレストロイカに端を発した東ドイツの民主化運動(東欧革命)をきっかけにベルリンの壁が崩壊し、翌1990年に東西ドイツの再統一を果たし、首都を再びベルリンとした。


17.ボンからの連邦政府機関移転(実質的な首都機能移転)や東ベルリンを中心とするベルリンの再開発・インフラ整備を進め、2001年5月2日に、ベルリンへの首都機能移転が完了した。


18.現在ではヨーロッパで最大の国家の一つになる。しかし、東西分裂を原因とする東西の経済格差が影を落としている。
それでもなお、ドイツはフランスとともに欧州連合(EU)の中核国として発言力を増し続けている。
これを再びドイツが周辺国の脅威となると懸念している国もある。

2011年10月27日木曜日

Scalaのファイル入出力のサンプル

Scalaでファイルを入出力するサンプルを書いてみました。
ファイルの入力(読み込み)は専用のクラスがあるのですが、ファイルの出力に関してはなんだか適切な物が無いようです。
なので、ファイルの出力に関してはJavaのクラスを使っています。

ファイルを新規作成して文字列を出力(すでに存在する場合は追記)
その後、作成したファイルを読み込んでいます。
/**
 * Scalaでファイルの入出力
 * Javaのクラスを使ってファイルを作成し、Scalaのクラスを使ってファイルを読み込む
 */
object FileIO {
    def main( args:Array[String] ) {

        // JavaのFileOutputStreamクラスとOutputStreamWriterを別名でimport
        // それぞれインスタンス生成時の1回のみの使用なので別名にする意味は特にないです。
        import java.io.{ FileOutputStream=>FileStream, OutputStreamWriter=>StreamWriter };

        val fileName = "test.txt"
        val encode = "UTF-8"
        val append = true
        
        // 書き込み処理
        val fileOutPutStream = new FileStream(fileName, append)
        val writer = new StreamWriter( fileOutPutStream, encode )

        writer.write("あいうえお\r\n")
        writer.write("かきくけこ\r\n")
        writer.write("さしすせそ\r\n")
        writer.close


        // 読み込み処理(コンソールに出力)
        // 1行で書くとこんな感じ
        // scala.io.Source.fromFile(fileName, encode).getLines.foreach{ println _ }
        val source = scala.io.Source.fromFile(fileName, encode)
        val lines = source.getLines
        lines.foreach{ println _ }


    }
}

2011年10月26日水曜日

Scalaのアクセサメソッドの挙動

Scalaのアクセサメソッド(getterとsetter)について調べたことをまとめます。

下記ページをかなり参考にさせていただきました。
[Scala][Java] Scalaの統一アクセス(プロパティ構文)がなかなかイカしてる件

Scalaはvarかvalを使ってプロパティを宣言すると、自動的にアクセサメソッドを生成してくれます。
さらに、プロパティを直接参照するような書き方をすると、自動的にアクセサメソッドが実行されるようになっています。
そのため、

オブジェクト名.name で、自動生成されたゲッターが実行される
オブジェクト名.name = "abc" で自動生成されたゲッターが実行される

となります。

コンパイルした後に、javapを使って中身を覗いてみると宣言していないメソッドが生成されていることが分かります。

サンプルソース
class Hoge1 {
    var name:String = _
}

object Hoge1Runner {
    def main(args:Array[String]) {
        val obj = new Hoge1
        obj.name = "Tarou";

        // 実行結果は、「Hoge1:Tarou」となる
        println("Hoge1:" + obj.name);
    }
}
javap -private Hoge1の実行結果
  public class Hoge1 extends java.lang.Object implements scala.ScalaObject{
      private java.lang.String name;
      public java.lang.String name();
      public void name_$eq(java.lang.String);
      public Hoge1();
  }

自動的に生成されたアクセサメソッド使ってるって言ってもこれじゃJavaのpublicなプロパティと一緒じゃん。
値のチェックとか必要な場合は結局アクセサメソッド自前で作らなきゃいけないんでしょ?オーバライドできるの?
ということでアクセサをオーバライドしてみました。(オーバライドって言い方が正しいかどうかは分かりませんが)
getterでは、先頭に「Mr.」を、setterでは末尾に「.」を付与するようにしました。

Hoge1Runnerのrun()と、Hoge2Runerのrun()を見比べてみてください。呼び出し側の実行方法は全く変わっていません。
つまり、サクっと開発しておいて、後々呼び出されるクラスの方を修正してしまえば、呼び出し側を変更する必要が無いのです。
Javaだとこうはいきません。オブジェクト名.プロパティ名と書いたコードが山ほどあった場合、呼び出されているクラスでアクセサメソッドを追加した際、呼び出しているプログラムを全て修正する必要があります。
IDEを使っていればアクセサメソッドを自動生成してくれたり、一括置換など便利な機能があるので、特に困ることは無いかもしれませんが、ちょっとしたツールを作りたいという時にはこう言った機能が真価を発揮すると思います。

問題点として、以下のjavap実行結果を見て分かる通り、自動生成されたgetterであるname_()が定義されています。
ということは、実用上問題はないでしょうが、Hoge2#name_ = "aaa" などが実行されると意図したgetterが利用されないということになります。

サンプルソース
class Hoge2 {
    var name_ :String = _

    // getter
    def name  = {
        "Mr." + name_
    }

    // setter
    def name_= (value:String) = {
        name_ = value + "."
    }
}

object Hoge2Runner {
    def main(args:Array[String]) {
        val obj = new Hoge2
        obj.name = "Tarou";

        // 実行結果は「Hoge2:Mr.Tarou.」となる
        println("Hoge2:" + obj.name);

        // 以下の方法だと、用意したgetterが使われないので、実行結果は「Hoge2:Tarou」となります
        //(用意したsetterを使ってないのでピリオドがつかない)
        // val obj2 = new Hoge2
        // obj2.name_ = "Tarou"
        // println("Hoge2:" + obj2.name);
    }
}
javap -private Hoge2の実行結果
public class Hoge2 extends java.lang.Object implements scala.ScalaObject{
    private java.lang.String name_;
    public java.lang.String name_();
    public void name__$eq(java.lang.String);
    public java.lang.String name();
    public void name_$eq(java.lang.String);
    public Hoge2();
}

Hoge2の、意図しないgetterが利用できる問題を解決するためには、プロパティ自体をprivateにする必要があります。
プロパティをprivateにすると、自動生成されるgetterとsetterもprivateになります。
そのため、自動生成されたアクセサには、外部からアクセスでできなくなるため、意図しないアクセサ(自動生成されたアクセサ)が利用できてしまう問題を解消できます。
ただ、いきなりこの形で記述してしまうとScalaでプロパティが自動生成されるメリットが無くなってしまいます。
まずはpublicでプロパティを作っておいて、問題が出たりするタイミングで修正した方が良いかも。
setter自体を用意しなければ外部からの更新を制御することもできます。

サンプルソース
class Hoge3 {
    private var name_ :String = _

    // getter
    def name  = {
        "Mr." + name_
    }

    // setter
    def name_= (value:String) = {
        name_ = value + "."
    }
}

object Hoge3Runner {
    def main(args:Array[String]) {
        val obj = new Hoge3
        obj.name = "Tarou";

        // 実行結果は「Hoge3:Mr.Tarou.」となる
        println("Hoge3:" + obj.name);
        // 以下の方法だと、name_はprivateなのでコンパイルエラー
        // (error: variable name_ in class Hoge3 cannot be accessed in Hoge3)

        // val obj2 = new Hoge3
        // obj2.name_ = "Tarou"
        // println("Hoge3:" + obj2.name);
    }
}

javap -private Hoge3の実行結果
public class Hoge3 extends java.lang.Object implements scala.ScalaObject{
    private java.lang.String name_;
    private java.lang.String name_();
    private void name__$eq(java.lang.String);
    public java.lang.String name();
    public void name_$eq(java.lang.String);
    public Hoge3();
}

Scalaではプロパティのアクセサは自動生成されるなら、そのアクセサはどうやって修正すればいいんだ?と思って調べた結果をまとめました。
間違っている点などあればご指摘頂頂けるとありがたいです。
ちなみに、プロパティをvalで宣言すると、Javaのfinalになり、setterは自動生成されず、getterのみ自動生成されます。
Javaのfinalなので、同じクラス内からも当然値を変更できなくなります。
なんでプロパティ名にアンダーバーが必要なの?というのはまだ理解できていません。
アクセサ自体の書き方も、普通の関数とは違うようなのでまだまだ勉強しなければという感じです。

2011年10月6日木曜日

Eclipse3.7にGoogle Plugin for Eclipseをインストールしようとするとエラーが発生する

Eclipse3.7(Indigo)にGoogle Plugin for Eclipseをインストールしようとすると下記のエラーが発生しました。

1 つ以上の必須項目が見つからないため、インストールを完了できません。 Software being installed: Google App Engine Tools for Android 2.4.1.r37v201109211906 (com.google.gdt.eclipse.mobile.android.feature.feature.group 2.4.1.r37v201109211906) Missing requirement: Android Cloud Tooling 2.4.1.r37v201109211906 (com.google.gdt.eclipse.mobile.android 2.4.1.r37v201109211906) requires 'bundle com.android.ide.eclipse.adt 12.0.0' but it could not be found Cannot satisfy dependency: From: Google App Engine Tools for Android 2.4.1.r37v201109211906 (com.google.gdt.eclipse.mobile.android.feature.feature.group 2.4.1.r37v201109211906) To: com.google.gdt.eclipse.mobile.android [2.4.1.r37v201109211906]

なんかAndroid用のプラグインの依存関係が解決できないよ、というようなエラー。

これは、最初の「使用可能なソフトウェア」のところで、Google App Engine Tools for Android (requires ADT)のチェックを外して上げると解決します。
Android使わないし!という人はこれでも問題ないかと。

2011年10月5日水曜日

ScalaでHashtable系を使ってみる

object Hoge {
    def main(args:Array[String]) {
        import java.util.Hashtable

        // ----------------------------
        // 一番シンプルなパターン
        // ----------------------------
        // Javaだと Hashtable <String,String> hTable = new Hashtable <String,String>();
        val hTable = new Hashtable[String,String]()
        hTable.put("key1", 1.toString)
        hTable.put("key2", 2.toString)

        println(hTable.get("key1"))
        println(hTable.get("key2"))

        println("--------")

        // ----------------------------
        // リストに突っ込んでみる
        // ----------------------------
        //var hTableList:List[Hashtable[String, String]] = List()
        var hTableList = List[Hashtable[String, String]]()
        for ( i <- 1 to 10 ) {
            val hTable = new Hashtable[String,String]()
            hTable.put( "key", i.toString )
            hTableList = hTableList ::: List(hTable)
        }
        hTableList.map( record => println( record.get("key") ) )

        println("--------")

        // ----------------------------
        // せっかくなのでScalaのMapを使ってみる
        // ----------------------------
        //var tableList:List[Map[String,String]] = List()
        var tableList = List[Map[String,String]]()
        for ( i <- 1 to 10) {
            tableList = tableList ::: List( Map("key" -> i.toString) )
        }
        tableList.map( record => println( record.get("key") ) )

        println("--------")

        // ----------------------------
        // リストをもう少しかっこよくする
        // ----------------------------
        val listBuffer = new scala.collection.mutable.ListBuffer[Map[String,String]]
        for ( i <- 1 to 10 ) {
            listBuffer += Map( "key" -> i.toString )
        }
        listBuffer.toList.map( record => println(record.get("key")) )
    }
}

2011年8月8日月曜日

Scalaでユニットテスト

ターミナルとかプロンプトで実行する場合。

scalatestと、JUnitのページからそれぞれ必要なjarファイルをダウンロードする。(今回はJUnit4)
結果的にscalatest-1.5.1.zipとjunit-4.9b3.jarが手に入る。
scalatestは解凍するとscalatest-1.5.1.jarがあるので、こいつとjunit-4.9b3.jarをScalaのインストールディレクトリ内にあるlibディレクトリの中に突っ込んで準備完了。
libディレクトリに置いておきたくない場合は、コンパイル時と実行時に毎回クラスパスに該当jarを指定すること。

テストのサンプルソースは以下のとおり。
プログラミング言語Scala 日本語情報サイト01.02.JUnit 4 と ScalaTest の始め方の物をそのまま使わせていただいています。(先頭にコメントを追加)

//import org.scalatest.junit.AssertionsForJUnit
import org.scalatest.junit.JUnitSuite
import scala.collection.mutable.ListBuffer
import org.junit.Assert._
import org.junit.Test
import org.junit.Before


/**
 * /////////////////////////////////////////////////////////////////////////////////////////////
 * Scalaでユニットテストのサンプル
 * クラスパスに、JUnitとscalatestのjarファイルを加えておく必要がある。
 * 通常の開発環境であれば、SCALA_HOME/lib/の下に置いておけば自動的にクラスパスに含まれるので楽。
 * /////////////////////////////////////////////////////////////////////////////////////////////
 * JUnitで実行する場合は以下のコマンド
 * scala org.junit.runner.JUnitCore ExampleSuite
 *
 * scalatestで実行する場合は以下のコマンド
 * scala org.scalatest.tools.Runner -p . -o -s ExampleSuite
 * ちなみに、 -p . の . を省けばSwingウインドウが起動する
 *
 * どちらで実行する場合でも、JUnitSuiteを継承していれば問題無し。JUnitSuiteはAssertionsForJUnitをtraitとして使っている
 */
//class ExampleSuite extends AssertionsForJUnit {
class ExampleSuite extends JUnitSuite {

    var sb:StringBuilder = _
    var lb:ListBuffer[String] = _

    @Before def initialize() {
        sb = new StringBuilder("ScalaTest は")
        lb = new ListBuffer[String]
    }

    // JUnitスタイルのアサーションを使用
    @Test def verifyEasy () {
        sb.append("かんたん!")
        assertEquals("ScalaTest はかんたん!", sb.toString)
        assertTrue(lb.isEmpty)
        lb += "sweet"
        try {
            "verbose".charAt(-1)
            fail()
        } catch {
            case e:StringIndexOutOfBoundsException => // こうなるはず
        }
    }

    // ScalaTest アサーションを使用
    @Test def verifyFun() {
        sb.append("たのしい!")
        assert(sb.toString == "ScalaTest はたのしい!")
        assert(lb.isEmpty)
        lb += "sweeter"
        intercept[StringIndexOutOfBoundsException] {
            "concise".charAt(-1)
        }
    }
}

2011年8月2日火曜日

gedit(Ubuntu)でドイツ語のスペルチェック

ドイツ語の勉強に、しっかり身につくドイツ語トレーニングブック を使っているのですが、さすがに手書きをしていると時間がかかりすぎるので、パソコンで練習問題をやっています。
エディタにはgeditを使っているのですが、geditにはスペルチェック機能が付いています。
これは勉強が捗るぞ!と思ったのですが、標準ではドイツ語はUbuntu(日本ローカライズされたVirtualBox用のUbuntu)でサポートされていないようなので、手動でインストールした結果、geditで正しくドイツ語のスペルチェックが出来るようになりました。

ドイツ語のインストール方法は、
システム→システム管理→言語サポート→言語のインストールと削除→ドイツ語にチェックを入れる→変更を適用
これでOKです。

2011年7月21日木曜日

スマートフォンのこれからの進化予想(ver1)

今後どういった形でスマートフォンが進化していくか考えてみました。
個人的には、スマートフォンと呼ばれている所謂携帯電話は、間違いなくPCを置き換えていくことになると思っています。
家の外では現在と同じような使い方で、家に帰った時にはドックのような物にセットすれば、現在PCで使っているようなサイズのディスプレイとキーボード、マウスが使えるようになるのではと。

キーボードに関しては既にBluetoothのものがあるし、ディスプレイに関してもAndroidであればHDMI経由でディスプレイに出力できる端末もあります。
CPU、メモリの性能が鍵になると思いますが、こちらに関しても今後ドンドン性能が上がっていくでしょう。
データの保存先はクラウド側にすればいいのであまり問題にはならないと思います。

個人情報に関して。
GoogleであったりFacebook、TwitterのIDを使って外部サイトの認証が出きるサイト、サービスが増えています。
現状ではどのサービスが1番!という決め手がないので、各々が好きなサービスに登録して、サービスの提供側もメジャーなAPIは網羅するという形です。
今後はスマートフォンが個人情報のマスターになり、クラウド側は、プライマリのスマートフォンから許可を貰って個人情報を取得、そして個人情報のバックアップ側(スレーブ)になるのではないでしょうか。

以上、妄想していることはザックバランにまとめてみました。
個人的には当たらずとも遠からずあと思っています。
具体例や、こうすれば良いといったネタが思いついたらまた書きます。

2011年7月20日水曜日

Scalaでx桁の文字列を出力

ドキュメントとか書くときに、「ここにはx桁の文字列を記述してください」的な事をよく書きます。
サンプルデータとか特にそうですね。

例えば、md5の値は32文字なので、よくサンプルとして、


// md5には32文字の文字列が入ります。
String md5 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

と書きます。
32文字なんだから、サンプルも32文字書かないといけないのですが、数えながら書くのが面倒・・・
ということでScalaで32文字の文字列(今回はx)を出力する式を書いてみました。
REPLで実行すると以下の通りです。

scala> (for(i <- 1 to 32) yield {"x"}) mkString
res18: String = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

これでx...の部分をコピーすればOK

Scala、というよりREPLが便利?

今更Googleリーダー

今日から使い始めてみましたが、良いですね。
今まではiGoogleをRSSリーダー代わりにしてきましたが、Googleリーダーの方が多機能だし見やすいですね。
ただ調子に乗っていっぱい登録した挙句結局見るのがしんどくなりそうで怖い・・・

2011年7月16日土曜日

PlayFrameworkチュートリアルでcoberturaのエラー

最近、週末はPlayFrameworkの勉強をしています。
非公式のようですが、マニュアルが日本語化されているのでスムーズに勉強できます。
http://playdocja.appspot.com/

チュートリアルが逸脱で、今まで様々な環境のチュートリアルを見てきましたが、PlayFrameworkのチュートリアルは群を抜いて分かりやすいです。(といっても一回読んだだけで全てを理解するのは難しいですが)

基本的に書いてあるとおりに勉強していけば問題ないのですが、最後の方のテストの完了で躓いたので備忘録としてまとめます。

ページ下部の方に、コードカバレッジ計測、という項目がありますが、公式も含めてここに書かれている通りにしてもエラーが発生します。
説明どおりにapplication.confを修正してEclipseからPlayをテストモードで起動しても、Play終了時にcoberturaはコードカバレッジレポートを生成してくれません。
何故かというとPlay本体にはcoberturaは含まれていないからです。

以下、PlayをEclipseから起動した際のコンソールビューの内容です。
---------------------------------------------
Listening for transport dt_socket at address: 8000
00:09:42,662 INFO ~ Starting /home/dev-user/work/play_projects/yabe
00:09:42,666 WARN ~ Declaring modules in application.conf is deprecated. Use dependencies.yml instead (module.crud)
00:09:42,667 INFO ~ Module crud is available (/home/dev-user/local/play-1.2.1/modules/crud)
00:09:42,667 WARN ~ Declaring modules in application.conf is deprecated. Use dependencies.yml instead (module.secure)
00:09:42,667 INFO ~ Module secure is available (/home/dev-user/local/play-1.2.1/modules/secure)
00:09:42,667 WARN ~ Declaring modules in application.conf is deprecated. Use dependencies.yml instead (module.cobertura)
00:09:42,668 ERROR ~ Module cobertura will not be loaded because /home/dev-user/local/play-1.2.1/modules/cobertura does not exist
00:09:43,380 WARN ~ Actually play.tmp is set to null. Set it to play.tmp=none
00:09:43,391 WARN ~ You're running Play! in DEV mode
---------------------------------------------

なので、coberturaをインストールしなければなりません。
インストールにはplay installコマンドを使います。
プロジェクトディレクトリに移動したら「play install cobertura」を実行します。これだけでインストール完了です。
続けて「play test」を実行してからhttp://localhost:9000/@testsにアクセスして、テストを実行してからコンソールでctrl-cでPlayサーバを停止すると、正常にcoberturaがコードカバレッジレポートを生成してくれます。

ただし、Eclipseを使っている場合はこれだけではエラーになってしまいます。
通常、クラスパスを変更するような修正を行った場合、プロジェクトディレクトリで再度eclipsifyコマンドを実行する必要がありますが、今回はそれを実行してもEclipseからテストモードでPlayを起動してアクセスするとエラーが表示されてしまいました。



EclipseのコンソールビューはJavaのエラーが延々と
--------------------------------------------
Listening for transport dt_socket at address: 8000
20:43:48,811 INFO ~ Starting /home/dev-user/work/play_projects/yabe
20:43:48,816 WARN ~ Declaring modules in application.conf is deprecated. Use dependencies.yml instead (module.crud)
20:43:48,817 INFO ~ Module crud is available (/home/dev-user/local/play-1.2.1/modules/crud)
20:43:48,817 WARN ~ Declaring modules in application.conf is deprecated. Use dependencies.yml instead (module.secure)
20:43:48,817 INFO ~ Module secure is available (/home/dev-user/local/play-1.2.1/modules/secure)
20:43:48,817 WARN ~ Declaring modules in application.conf is deprecated. Use dependencies.yml instead (module.cobertura)
20:43:48,817 INFO ~ Module cobertura is available (/home/dev-user/local/play-1.2.1/modules/cobertura-2.1)
20:43:49,465 WARN ~ You're running Play! in DEV mode
~
~ Go to http://localhost:9000/@tests to run the tests
~
20:43:49,578 INFO ~ Listening for HTTP on port 9000 (Waiting a first request to start) ...
20:44:07,139 ERROR ~

@67578a30n
Internal Server Error (500) for request GET /@tests

Compilation error (In {module:cobertura-2.1}/app/controllers/Cobertura.java around line 6)
The file {module:cobertura-2.1}/app/controllers/Cobertura.java could not be compiled. Error raised is : play.modules.cobertura.CoberturaPlugin cannot be resolved

play.exceptions.CompilationException: play.modules.cobertura.CoberturaPlugin cannot be resolved
at play.classloading.ApplicationCompiler$2.acceptResult(ApplicationCompiler.java:246)
at org.eclipse.jdt.internal.compiler.Compiler.handleInternalException(Compiler.java:672)
at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:516)
at play.classloading.ApplicationCompiler.compile(ApplicationCompiler.java:278)
at play.classloading.ApplicationClasses$ApplicationClass.compile(ApplicationClasses.java:249)
at play.classloading.ApplicationClassloader.loadApplicationClass(ApplicationClassloader.java:150)
at play.classloading.ApplicationClassloader.loadClass(ApplicationClassloader.java:84)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at play.classloading.ApplicationClasses.getAssignableClasses(ApplicationClasses.java:61)
at play.classloading.ApplicationClassloader.getAssignableClasses(ApplicationClassloader.java:435)
at {module:crud}/app/views/tags/crud/types.tag.(line:3)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:213)
at play.templates.GroovyTemplate$ExecutableTemplate.invokeTag(GroovyTemplate.java:347)
at {module:crud}/conf/routes.(line:4)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:213)
at play.templates.Template.render(Template.java:26)
at play.mvc.Router.parse(Router.java:162)
at play.mvc.Router.parse(Router.java:190)
at play.mvc.Router.parse(Router.java:164)
at play.mvc.Router.load(Router.java:50)
at play.mvc.Router.detectChanges(Router.java:219)
at Invocation.HTTP Request(Play!)
20:44:07,561 ERROR ~

@67578a30o
Internal Server Error (500) for request GET /favicon.ico

Compilation error (In {module:cobertura-2.1}/app/controllers/Cobertura.java around line 6)
The file {module:cobertura-2.1}/app/controllers/Cobertura.java could not be compiled. Error raised is : play.modules.cobertura.CoberturaPlugin cannot be resolved

play.exceptions.CompilationException: play.modules.cobertura.CoberturaPlugin cannot be resolved
at play.classloading.ApplicationCompiler$2.acceptResult(ApplicationCompiler.java:246)
at org.eclipse.jdt.internal.compiler.Compiler.handleInternalException(Compiler.java:672)
at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:516)
at play.classloading.ApplicationCompiler.compile(ApplicationCompiler.java:278)
at play.classloading.ApplicationClasses$ApplicationClass.compile(ApplicationClasses.java:249)
at play.classloading.ApplicationClassloader.loadApplicationClass(ApplicationClassloader.java:150)
at play.classloading.ApplicationClassloader.loadClass(ApplicationClassloader.java:84)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at play.classloading.ApplicationClasses.getAssignableClasses(ApplicationClasses.java:61)
at play.classloading.ApplicationClassloader.getAssignableClasses(ApplicationClassloader.java:435)
at {module:crud}/app/views/tags/crud/types.tag.(line:3)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:213)
at play.templates.GroovyTemplate$ExecutableTemplate.invokeTag(GroovyTemplate.java:347)
at {module:crud}/conf/routes.(line:4)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:213)
at play.templates.Template.render(Template.java:26)
at play.mvc.Router.parse(Router.java:162)
at play.mvc.Router.parse(Router.java:190)
at play.mvc.Router.parse(Router.java:164)
at play.mvc.Router.load(Router.java:50)
at play.mvc.Router.detectChanges(Router.java:219)
at Invocation.HTTP Request(Play!)
---------------------------------------------------

EclipseからPlayを起動する際のクラスパスの設定が異なっているためで、eclipsifyではcoberturaを追加してくれない様です。

そこで、Eclipseの実行構成から、eclipsifyで自動的に生成されているサーバに、coberturaのjarファイルを手動で追加してあげる必要があります。







ユーザエントリーを選択して、外部Jar追加を選択後、cobertura/lib/*.jarを選択して追加してください。
それが終わった後にEclipseからPlayサーバをテストモードで起動すれば、問題なくcoberturaが動作します。

2011年7月13日水曜日

Javaで外部サイトのHTMLを取得する

PHPのfile_get_contents()は外部サイトのHTMLを取得できます。
さらに、クエリストリングを付与してなんちゃってサーバ間通信までできてしまいます。
Javaでもそんなの欲しいな~ということで作ってみました。

Windows7のコマンドプロンプトから実行して、EUC-JPのサイトのHTMLを取得、表示で問題なく動作しています。
ただ、文字コードを自動判別することろにJISAutoDetectを利用しているので文字化けする可能性があります。
文字コードを指定してあげれば問題ないと思います。

2011年5月23日月曜日

Scalaでテキストファイルを出力(Windows)

Windowsで以下のように実行すると文字化けします

scala.io.Source.fromFile("test.txt").getLines.foreach{ println _ }

fromFileにはファイルのエンコードを渡せるので、

scala.io.Source.fromFile("test.txt", "UTF-8").getLines.foreach{ println _ }

としてあげればOK

サンプルコードは別記事にあります