名前渡し=遅延評価だと勘違いしてた。

http://d.hatena.ne.jp/kujira16/20111119/1321708622
http://d.hatena.ne.jp/kanno_kanno/20130202/1359777436
http://d.hatena.ne.jp/xuwei/20120818/1345271478

勘違いしてました。
なので、引数は一度しか評価されないと。
念のため、自分でも確認。

scala> def log(msg: => String) { println(msg); println(msg) }
log: (msg: => String)Unit

scala> log({println("eval"); "Message"})
eval
Message
eval
Message

scala> 

うわっ、本当だ!
だから、「遅延評価」とは呼ばずに、「名前渡し」と呼ぶのか?

[scala]log4jを使う

探してみたら、以下のを見つけました。
よさげです。
http://stackoverflow.com/questions/2018528/logging-in-scala
traitになってて、とても使いやすそう。
それに、メッセージの引数が名前渡しになっているので、
出力しないメッセージにはCPUリソースを食わないようになっています。

[scala]log4jを使う

メモ。
Javaだとstaticなフィールドで使うのだけれど、scalaはclassとobjectに分かれているので、一瞬悩みます。
遅延評価も有効だろうとの判断からlazyにしています。


これであってるかな?

import org.apache.commons.logging.LogFactory
import org.apache.log4j.xml.DOMConfigurator

// エントリとなるオブジェクト
object Foo {
  DOMConfigurator.configure("./log4j.xml");
  private lazy val logger = LogFactory.getLog(Foo.getClass)

  // ...
  logger.trace("Foo")
  // ...
  def main(args:Array[String]) {
    // ...
  }
}
import org.apache.commons.logging.LogFactory

object Bar {
  private lazy val logger = LogFactory.getLog(Bar.getClass)
}

class Bar {
  import Bar.logger
  // ...
  logger.trace("Bar")
}

antで環境変数の値を参照する

めも

    <property environment="env" />
    <property name="scala-home"  value="${env.SCALA_HOME}"/>

    <property name="scala-library.jar"  value="${scala-home}/lib/scala-library.jar"/>
    <property name="scala-reflect.jar"  value="${scala-lib}/scala-reflect.jar"/>
    <property name="scala-compiler.jar" value="${scala-home}/lib/scala-compiler.jar"/>

新規作成、開く、名前をつけて保存、上書き保存、終了をトレイトで

この記事は、Play or Scala Advent Calendar 2012 の24日目の記事です。
http://qiita.com/advent-calendar/2012/play-or-scala

概要

GUIアプリケーションを作るときに、ファイルメニューに「新規作成」「開く」「上書き保存」
「名前をつけて保存」というメニューを用意することがよくあります。
なんとか共通化できないかと思っていたのですが、
トレイトを使うといい感じに整理できたので紹介します。

前提・環境

ここでは、同時に複数のファイルが扱えないSDI(Single Document Interface)を想定しています。
メモ帳やペイントなどがそれにあたります。
また、GUIは javax.swingパッケージを使っています。
(scala.swingパッケージではありません)。

トレイトを使わない場合

単に「開く」と言ってもファイル選択するだけではなく、すでに現在のドキュメントが
編集されていたら、先に保存するかどうか問い合わせなければなりません。
保存する場合でも、編集中のドキュメントがファイルと関連付けられていないときには
保存するファイル名を入力させる必要があります。
擬似的なコードを書くと以下のようになります。

    /** [開く]のときの処理 */
    def actionPerformed(e:ActionEvent) {
      // 編集されていたら、
      if (modified) {
        // 保存しますか?と問い合わせる。
        // キャンセルならreturn
        if (Yesなら) {
          // ファイルと関連付けられてないとき、
          if (file == null) {
            // 保存用ファイル選択ダイアログを表示。
          }
          save(file)      // ★ココがアプリ固有の処理
          modified = false
        }
      }
      // オープン用ファイル選択ダイアログを表示。
      // 開くボタンを押したら
      open(file)          // ★ココがアプリ固有の処理
      modified = false
      // GUIを更新。
    }

これらの処理のうち、大半は紋切り型のコードです。
アプリ固有の部分は、★の箇所のopen()とsave()だけです。

なんとか共通化できないかと思っていたのですが、
トレイトを使うといい感じに整理できたので紹介します。
まぁ、共通部分をstaticなメソッドにしたりすればある程度共通化できるのですが、
どうもしっくりきませんでした。

トレイトを使った場合

以下がそのトレイトになります。
GUIアプリケーションには、ビューアとエディタの2種類が考えられるので、
SingleDocumentViewerとSingleDocumentEditorの2つのトレイトに分けました。

trait SingleDocumentViewer {
	self: JFrame =>  // 自分型の指定

	var file:File = null
	def open(file:File)
	def updateFrame()

	val fileOpenAction:Action = new FileOpenAction()
	val fileExitAction:Action = new FileExitAction()

	class FileOpenAction extends AbstractAction {
		// 中略
	}

	class FileExitAction extends AbstractAction {
		// 中略
	}
}


trait SingleDocumentEditor extends SingleDocumentViewer {
	self: JFrame =>  // 自分型の指定
	var modified = false

	def init()
	def save(file:File)

	val fileNewAction = new FileNewAction()
	override val fileOpenAction = new FileOpenAction()
	val fileSaveAction = new FileSaveAction()
	val fileSaveAsAction = new FileSaveAsAction()
	override val fileExitAction = new FileExitAction()

	def inquireSave(parentComponent:JFrame):Boolean = {
		// 中略
	}

	class FileNewAction extends AbstractAction {
		// 中略
	}

	class FileOpenAction extends AbstractAction {
		// 中略
	}

	class FileSaveAction extends AbstractAction {
		// 中略
	}

	class FileSaveAsAction extends AbstractAction {
		// 中略
	}

	class FileExitAction extends AbstractAction {
		// 中略
	}
}


まだ荒削りで、考慮すべき点は多いですが、おおむねイイ感じにできています。
ソースはこちら。
http://www.hcn.zaq.ne.jp/no-ji/memo-scala/Advent2012.zip
サンプルとして、テキストパッドと画像ビューアを用意しました。
短いソースですが、ファイルメニューに関しては充実しています。

まとめ

GUIアプリでのトレイトの使い方ですが、
他にも、クリップボード3兄弟、最近使ったファイル、多言語対応、アプリの起動&終了、
などにも適用できるのではないかと考えてます。

ちなみに

ちなみに、今日は私の誕生日です。(*^_^*)

Scala Advent Calendar 2012

めも。
去年、初めてこーいうイベントがあることを知って、今年は参加することにしてみました。 一番上のやつ。
でも、探したらほかにもあった。


Play or Scala Advent Calendar 2012
http://qiita.com/advent-calendar/2012/play-or-scala

Scala Advent Calendar jp 2012
http://partake.in/events/3407d5d2-435c-4354-a96e-1ab9b18bef73

Scalaz Advent Calendar
http://partake.in/events/7211abc9-ebb8-4670-b912-3089dc5e0edd