はい、というわけで。
Scala-ja - Scala勉強会@関東-2でLiftについて発表してきましたよ。
Scala勉強会@関東-2 終了 - Scalaとか構文解析についてあれこれ書く日記
発表資料はこちら。
まず、発表する段階でPCセットアップしようとして、VGAアダプタを忘れてくるという醜態をさらす。
結局、発表順を入れ替えてもらってSofmapに買いに走るというダメっぷりをキメた!!
あと、Wiiリモコンでプレゼンをやってみよう!と思ったが、当日はWiiリモコンを認識してくれなくてあきらめた。
発表の方も、Mavanコマンドに失敗したりでうまくいかないところが多かった。
時間も足りなくて最後までやれなかったし。
反省点は多いぞ。
まぁいろいろダメだったけど、発表してよかった。
で、作る予定だったLiftで実装したTropyクローンは、Githubにあげておきます。
興味のある人は触ってみたり、もっとScala的に書き直したりしてみてくれると幸せになれます(オレが)。
liftropy/target at master · yuroyoro/liftropy · GitHub
全体的な感想。
- 何となくアカデミックな雰囲気(場所が東大の研究室だったから?)
- Haskellとかの前提知識が不足してた。もっと勉強が必要だオレは。
- Hands onみたいに、みんなでコード書いてみよう的なイベントがあるとおもしろいかも?
- 内容的にかなり濃い感じ。だがそれがいい。
- 懇親会でのアツさ。ってかC++0x?
参加された皆さん、お疲れ様でした!
Memo
■Scalaチュートリアル
2.7.2
scalaのGenericがjavaから見えるようになった
Javaとの相互依存したプログラムがコンパイル可能
if else → elseを核と値を返す ?みたいな
書かない場合はUnit型の値が帰る
forでコレクション要素について繰り返し
forで配列やリストなどを生成できる for(x <- 1 to 50;y <- 1 to 50 if y == x * x ) yield( x,y)
実はmap,flatpap,filterのメソッド呼び出しへのsyntax sugar
whileはforよりも冗長だけど高速
高階関数
foldLeft 関数を引数にとる関数
def open(path:String)(block:InputStream => Unit){
var in =new FileInputStream(path)
try{block(in)}finally{in.close}
}
引数なしメソッドの呼び出しで()は諸略できる
クラス定義
クラス名に続けてコンストラクタ引数を定義
valをつけると外部から読み取り可能
引数のスコープはクラス定義全体
演算子は通常のメソッドとして定義
def thisを定義するとコンストラクタをOverloadする
trait
インスタンス生成できない。多重継承。ようはMixin。RubyのModuleなど。
object - Singletonを作る。クラスと同様superclassを指定できる。
implicit conversion
暗黙の型変換
implicit def int2Dtring( i :Int):String =i.toString
Int型に存在しないメソッドの呼び出しを検出
→Stringへの暗黙の変換をコンパイルが試みる
危険な変換を定義しないようにするのは自己責任( String2Intなど)
class RangeExt( range:Range){
def exclude(elem :Int )=range.filter(e => e!= elem)
}
implicit def range2RangeExt( f :Range) :RangeExt = new RangeExt(r)
既存のクラスにメソッドを追加するなどで使われる
パターンマッチング
式 match { case パターン => ....}
switch分をより強力に
パターンにマッチした値を変数に束縛可能
構造を持つデータをパターンマッチに使える collectionなど
case Array
Case Class -パターンマッチに使える MLとかのalgebraic datatype
Extractor
既存の型に新しいパターンを定義する機能
unapplyメソッドで動作を定義する
Structural type
静的に型チェックされるduck typing
特定のシグニチャのメソッドをもっているかのみがチェックされる
def printName(x:{def name():String}) =println(x.name)
Lazy value
部分的な遅延評価
lazy val x =println("x")
一度評価された値は再計算されない
Partial function
引数から値を計算できるを isDefinedAtによって関数を実行することなく得られる
Actorライブラリ等で活用
lazy val fib :PartialFunction[iInt:Int] ={
case 0 |1 =>1
case
パターンだけを評価できる
XMLリテラル
XMLの構造に対するパターンマッチング
XMLノードの走査が楽に
list match{
case <ul>{items@_*}</ul> =>item.foreach
Generics val x:Array{String] = Array("A","B","C")
クラス名の後に[型パラメータ]
型パラメータは普通の型で扱える
implicit parameter
引数にimplicitを付加
呼び出し側のスコープでimplicitな値が定義されていれば明示的に渡さなくても良い
implicit object
ScalaCheckでよく使われる
Existential type
Array[String]はArray[AnyRef]のサブタイプではない
Array[T} forSom {type T}
任意の型の配列のスーパータイプ
書き込み不可
■ASN.1ライブラリをScalaでDSL風に(tmiyaさん)
肝心な本編が聞けなかったorz
ライブラリの作り方
各*.scalaファイルをobject Foobli{}で囲む
使うコード側でImport
Enumの作り方
scalaのEnumはなんか使いにくい
自分でobject作った方がいい
Patternマッチ便利すぐる
value objectはcase classにしておく
Option[T]は便利
何もない場合nullではんく Some(t)とNoneで場合分け
HaskellのMaybe monad.どこかで
implicit conversionは便利
既存クラスにメソッドを追加したい場合
■Parser Combinator
yaccやJavaCC
scala.uti.parsing.combinator
基本的なパッケージ
scala.uti.parsing.combinator.lexical
字句解析
scala.uti.parsing.combinator.syntacical
便利に使うためのパッケージ
()の対応をチェックするパーザ
Parsar[T]
基本クラス Parsarを組み合わせる
extends (Reader) => Parsers.ParseResult[T]
ストリームを受け取り解析結果を返す関数
Reader[T] :T型のストリーム
副作用はなし
一種の無限リスト
Parsers.ParseResult[T]
success[T](result : T, next :Reader)
Parsers{type Elem}
このクラスを継承し、サブクラスで文法を定義する
Elem : 入力列
elem(e:Elem)
eにマッチするかを検査するパーザを生成
implicit conversionによてElem → Parser[Elem]の変換が定義されてるので通常使わない
p ~ q
パーザを連結
p | q
パーザの順序付き選択
まず最初にpがマッチするか試し,pが失敗した場合のみバックトラックしてqを試す。
p ||| q
順序なし選択。両方マッチし、より長い文字列にマッチした方が解析結果となる
p *
pの0回以上の繰り返し
p ^^ f
pが成功したときに関数fを実行
p:Parser[T]
f:T=>V
p ^^ f ::Parser[V]
StanderdTokenParsersがよろしくやってくれる
入力をTokenとして扱ってくれる
空白の読み飛ばし
予約語
JSONパーザ
Lexer( scala.util.parsing.json.Lexer)
■ScalaCheck
自動UnitTestツール
propertyによる振る舞いの定義
テストデータの自動生成
失敗するケースの最小値の探索
sbazを使ってインストール
2.7.2 finalではバイナリはどうさせず
svnからソース落としてant jar
property((a:A1,b:A2,...) =>booleanである型が満たす性質を記述する
prop#checkでテストする
Property テスト可能な基本単位
orc.scalacheck.Propのインスタンス
生成する型の判定 - implicit parameter
基本的な型のみ
たとえば自分で作ったクラスとかはimplicit objectであらかじめ宣言しておく