2012年3月17日土曜日

Scala 2.9.1.finalのインタプリターIMainでバグ

Scala 2.9.1.finalでインタプリタのIMainをいじっていたら、
インタプリタ内で定義した値を取得するメソッド であるvalueOfTermが常にNoneを返すので、
調べてみたら、このページに行き着いた。

https://issues.scala-lang.org/browse/SI-4899

どうやら、2.9.1のバグらしく2.9.0-1では、ちゃんと動くらしい。

2.9.1でインタプリタ内で定義した値を取得するには、valueOfTerm使わずに取得しなければならない。

IMainにprevRequestListというprotectedのメソッドがあり、

これは、List[Request]を返すが、このRequestを使って値を取得できるようだ。

たとえば、以下のようにすれば、取得できる。

 class MyIMain( s:Settings ) extends IMain( s ) {
 def lastRequest = prevRequestList.last
 }

 val settings = new Settings
 settings.usejavacp.value = true
 val main = new MyIMain(settings)
 main.quietImport("java.util.Date")
 main.interpret("val d = new Date")
 println(main.lastRequest.lineRep.call("$result"))
 main.close()

2012年2月11日土曜日

ScalaのActorとsleep

ScalaのActorの中でThread.sleepを使っていたら、どうも平行に処理されていないような気がして調べてみました。

 例えば、javaのThreadを使って以下のようなコードを実行する。
      1 to 10 map( n => (new Thread() {
 override def run = {
   println("start "+n)
   Thread.sleep( 3000 )
   println("done "+n)
 }
      }).start )
結果の出力は、以下のように、ほぼ同時に10個のスレッドがスタートして、 3秒後にそれぞれ終了する。
これは、予想通り。
start 10
start 4
start 6
start 2
start 3
start 8
start 9
start 7
start 1
start 5
done 10
done 4
done 6
done 2
done 3
done 8
done 9
done 7
done 1
done 5
これをActorを使って書き換える。
      1 to 10 map( n => Actor.actor {
 println("start "+n)
 Thread.sleep( 3000 )
 println("done "+n)
      })
このコードを実行した結果。
start 1
start 6
start 8
start 7
start 3
start 5
start 2
start 4
done 1
done 6
done 8
start 9
start 10
done 3
done 7
done 4
done 2
done 5
done 9
done 10
この結果をみると、最初の8個のスレッドは、ほぼ同時にスタートしているのがわかるが、 残りの2つは、最初にスタートしたスレッドが終わるのを待ってから、3秒後にそれぞれスタートしている。 

なぜ? 

どうやらこれはActorのプールに関係しているらしい。
 詳しくは分からないが、Thread.sleepを使った場合、 並列に実行できるのは、CPUのスレッド数のみのようだ。
それ以上に、並列に実行したいので、Thread.sleepを使わずに、 receiveWithinを使ったらうまくいった。
      1 to 10 map( n => Actor.actor {
 println("start "+n)
 Actor.self.receiveWithin( 3000 ) { case TIMEOUT => {}}
 println("done "+n)
      })
仕方ないので、この方法でやるかなぁ。

2012年2月10日金曜日

Liftでのプロパティファイル扱い

Liftのアプリケーションでいくつかのプロパティファイルを使い分けたい場合があります。
例えば、本番環境とテスト環境でDBの接続先を変えたい場合などです。
そうした場合、Liftは、プロパティファイルの名前によって使用するプロパティファイルを決めているようです。 基本的な、命名規則は、
modeName.userName.hostName.props
で、名前によって以下の順で優先的に読まれます。
/props/modeName.userName.hostName.props
/props/modeName.userName.props
/props/modeName.hostName.props
/props/modeName.default.props
/modeName.userName.hostName.props
/modeName.userName.props
/modeName.hostName.props
/modeName.default.props

nodeNameは、使用しているRun Modeのことで、例えば、"test"、"staging"、"production"、"profile"などを指定します。
"development"モードを使っている場合は、nodeNameは、省略してください。nodeNameに"development"って書いちゃうと、"development"モードとして正しく認識されないので注意が必要です。

userNameは、使っているOSのユーザ名にしなければならないようです。

 私の場合は、自分のローカルPCでは、リポジトリにあがっているプロパティファイルではなく 独自のプロパティファイルを使いたいので、自分の名前のプロパティファイルを作っています。
リポジトリにあがっているものは、本番で使うプロパティファイルで、 default.propsという名前にしてて、自分のPCでは、hogehoge.propsという名前にして、これはリポジトリの管理下においていません。

2012年2月6日月曜日

Emacsでclojure開発環境を整える

Emacsにclojureの開発を整えた時のメモ。

clojure-modeのインストール

  • EmacsでM-x package-install clojure-modeを実行する
  • init.elを編集
  • ;; clojure mode
    (require 'clojure-mode)
    
    ;; paredit
    (defun turn-on-paredit () (paredit-mode 1))
    (add-hook 'clojure-mode-hook 'turn-on-paredit)
    

slimeのインストール

  • EmacsでM-x package-list-packageを実行
  • slimeとslime-replにカーソルを合わせてiを押す
  • xを押してインストールを実行

Leiningenインストール

Leiningenは、clojureのビルドツール。
  • ここのページのDownload the scriptからシェルスクリプトをダウンロードしてくる
  • $> wget https://raw.github.com/technomancy/leiningen/stable/bin/lein
    
  • 権限を変えてパスの通った場所に置く
  • $> chmod 755 lein
    $> sudo mv lein /usr/bin/.
    

swank clojureのインストール

  • 以下のコマンドを実行してインストール
  • $> lein plugin install swank-clojure 1.4.0
    

プロジェクトの作成

$> lein new projectname

Emacsでreplを起動

 M-x clojure-juck-in

開いているバッファをコンパイル

 C-c C-k

EmacsにMarmaladeをインストール

Emacsのパッケージ管理システムであるMarmaladeをインストールしてみました。
  • Marmaladeからpackage.elを取得する
  • $> cd ~/.emacs.d/elisp
    $> wget http://repo.or.cz/w/emacs.git/blob_plain/1a0a666f941c99882093d7bd08ced15033bc3f0c:/lisp/emacs-lisp/package.el
    
  • init.elにmarmaladeの設定をする
  • (require 'package)
    (add-to-list 'package-archives
                 '("marmalade" . "http://marmalade-repo.org/packages/"))
    (package-initialize)
    
  • EmacsでM-x package-list-packageとするとインストールできるパッケージのリストが表示される
  • インストールしたいパッケージにカーソルを合わせてiを押せば選択できる
  • xでインストールを実行する

2012年1月14日土曜日

Scalaの関数オブジェクト

Scalaの関数オブジェクトの定義方法はいくつかの方法があってややこしいので、まとめてみた。

まず、きちんと書いた場合。
宣言時に引数の型と戻り値を指定している。
 val f:(Int => Int) = (x:Int) => x + 1

括弧をとってもいいようだ。
 val f:Int => Int = (x:Int) => x + 1

でも、関数の本体定義部分の括弧を取っちゃダメ
 val f:Int => Int = x:Int => x + 1

宣言時に型を書かないくてもOK
 val f = (x:Int) => x + 1

関数定義の部分の引数を書かなくてもOK
 val f:(Int => Int) = x => x + 1

でも、次のような横着はできないらしい
 val f = x => x + 1

引数が2つある場合
 val f:(Int,Int) => Int = (x:Int, y:Int) => x + y + 1

引数が1つのときと同様に、以下のようにも書ける
 val f = (x:Int, y:Int) => x + y + 1
 val f:(Int,Int) => Int = (x, y) => x + y + 1
結局、こうやって書くこと多い気がするなぁ
 val f = (x:Int, y:Int) => x + y + 1