エンジニアがJavaやscalaやLLについて語ります。We Love Engineering!!

ブログ

QCon Tokyo 2010 にて講演を行ないました。Scala+Liftによる超実用開発

本日、

■Scala+Liftによる超実用開発 ■ と題して、

InfoQ主催のテクニカルカンファレンス、QCon Tokyo 2010にてScala+Liftの講演を行なってきました。
「Scala(+Lift)は、実務で使えるの言語(+フレームワーク)だ!」という事を伝えたかったのですが、

いかがでしたでしょうか?
この講演をきっかけに、1社でもScalaを業務で使うようになって頂ければと思っております。

以下、講演の大まかな内容と、講演資料です。
皆様のご参考になれば、と思います。

■講演資料

10-04-20-qcon-tokyo-2010

■講演の大まかな流れ

  1. 世界Scala化の流れ(世界中でのScala採用事例の紹介
    • 採用事例紹介
    • 採用動機紹介
  2. パテントビューロがScalaを採用するに至った経緯
    • 当時の状況説明
    • 採用動機紹介
  3. パテントビューロでの採用事例
    • JavaをScalaにリプレース
    • Scalaで転職サイトを新規作成
    • その他、活用事例
  4. Lift概要
  5. Liftの便利機能紹介
    • View First
    • Liftのテンプレート紹介
    • Ajax対応
  6. Scala(+Lift)を実務で使ってみた感想
  7. Scala(+Lift)に関する不安を解消
    • 不具合
    • 開発環境
    • 教育コスト
  8. Liftと一緒に歩むScala中級者への道
  9. 開発者とデザイナによる、Scala(+Lift)に関するインタビュー
    • 中国、千葉、大阪、静岡の各県代表者より
  10. おまけ(JavaとScalaコードの比較)

カテゴリー: 未分類 | 1 件のコメント »

Scala 2.8 - 改善された対話型コマンドインターフェイス

Scala 2.8では対話型コマンドインターフェイス(REPL)がかなりいい感じになっています。

タブでコード補完

REPL上で下記のように入力してから

scala> “a”.

タブを入力すると、Stringメソッドが持つメソッドが一覧でみられます。

また、下記のようにメソッドが一意に決められる場合は

scala> “a”.to

一覧ではなく、メソッドがそのまま補完されます。

scala>”a”.toString

上記はStringリテラルに対してコード補完を行っていますが、他にもコード補完ができるものがあるので確認していきます。

インスタンスのメソッド、フィールド

scala>class Person(val firstName:String, val lastName:String) { def fullName = firstName + ” ” + lastName }

scala>val person = new Person(”yoshinori”, “ishii”)

scala>person.l

scala.person.lastName

→lastNameが保管される

scala>person.f

→firstNameとfullNameが一覧で出る。

privateメソッドは補完されませんが、protectedメソッドは補完されます。

パッケージ

scala>import scala.collection.

→scala.collectionパッケージ以下のパッケージ名とクラス名の一覧

型エイリアス

scala>type StrList = List[String]

scala>val strList:StrList = List(”a”,”b”,”c”)

scala>strList.sor

→sort、sortBy、sortWith、sorted の一覧

シェル上のパス

カレントディレクトリに script.scalaというファイルがある場合

scala>:load scr

以下のように保管されます。

scala>:load ./script.scala

もちろん :load がなくても、普通のシェルと同じ様にパスが補完できます。

追加されたコマンド

scala>:help

を実行すると、:cp:history:power:sh:silent というコマンドが追加されているのが確認できます。

:cp コマンド

クラスパスにJarまたはディレクトリを追加することができます。

scala>:cp myFantasticProgram.jar

コード補完も効くのでこの機能はうれしいですね。

環境変数の展開とかをやってくれるかと思いましたができませんでした。。

:history コマンド

実行したコマンドの履歴が一覧で表示されます。

scala>:history

498 :cp myFantasticProgram.jar

499 import jp.co.patentbureau.util._

500 :history

さらに履歴番号を入力することで、コマンドを再実行できます。

scala>:history 499

:h? コマンド

実行したコマンド履歴を検索出来ます。

scala>:h? List

161 val ls = List(”a”,”b”,”c”)
171 val l = List(1,2,3)
259 List(null).headOption

:power コマンド

パワーユーザモードで実行できるようにするコマンドで、:dump:searchなどのコマンドが追加されます。
このコマンドに関しては情報が少なすぎる上に、1エントリくらいの分量がありそうなので、説明は省略します。(時間あったら調べます^^;)

:sh コマンド

シェルを起動して、シェルのコマンドを走らせることができます。

scala>:sh mv myFantasticProgram.jar myFancyProgram.jar

:silent コマンド

結果を自動で出力する機能をON/OFFします。

scala>:silent

Switched off result printing.


OFFにすると、「res0:List[Int] = List(1)」などの出力がなくなります。

再度 :silentコマンドを実行すると、もとに戻ります。

scala>:silent

Switched on result printing.

感想

追加された機能は実用的なものばかりで、新規Scalaユーザの勉強にも役立つ思います。

コマンドがプラグインとかで追加できて

scala> :mvn net.liftweb.lift-util:2.0-M2

とかで、コード補完しながらmavenリポジトリのjarが追加できたりするといいなぁとか思いました。

Scalaでデザインパターン 【Chain of Responsibility】

Scalaでデザインパターンを再現するコーナー。

今回は 【Chain of Responsibility】パターンです。

Chain of Responsibility っぽいことを trait を利用して実装してみる

Scalaでデザインパターン(Chain of Responsibility)

上記のサイトなどでは、traitによる実装をしているので、PartialFunctionを使ってやってみました。


object Logger extends Enumeration {
val ERROR = Value(1)
val NOTICE = Value(2)
val DEBUG = Value(4)

private var _loggers: List[Logger] = Nil
private var initialized = false
def init(loggers:List[Logger]) =
if (!initialized) { _loggers = loggers; initialized = true }
else throw new IllegalStateException("Logger is already initialized")
def message(level:Logger.Value, msg:String) = _loggers.filter(_.isDefinedAt(level,msg)).foreach(l => l(level,msg))
}

abstract class Logger(val level:Logger.Value) extends PartialFunction[(Logger.Value, String), Unit] {
override def isDefinedAt(in:(Logger.Value,String)) = in._1 == level
}

class StdoutLogger(level:Logger.Value) extends Logger(level) {
override def apply(in:(Logger.Value,String)) = println("Writing to stdout: " + in._2)
}

class EmailLogger(level:Logger.Value) extends Logger(level) {
override def apply(in:(Logger.Value,String)) = println("Sending via email: " + in._2)
}

class StderrLogger(level:Logger.Value) extends Logger(level) {
override def apply(in:(Logger.Value,String)) = println("Writing to stderr: " + in._2)
}

Logger.init(new StdoutLogger(Logger.DEBUG) :: new EmailLogger(Logger.NOTICE) :: new StderrLogger(Logger.ERROR) :: Nil)
Logger.message(Logger.DEBUG,"It is debug message")

SingletonのLoggerを使っているのは新しくクラスを作るのが面倒だったからです。

元のChain of Responsibility の例に合わせるために、上記のような書き方をしましたが、PartialFunctionのリテラルをうまく使えば、もうちょっとクールな感じになる気がします。