情報科学若手の会日記Scalaの章

これは発表を聞きながらの走り書きメモなので間違っているかもしれません。

        • -

分量が多すぎたので分離

Scalaのifは値を返す。elseがないときUnitを返す。
x to yはx.to(y)と同じ。



Pythonのリスト内包みたいなのがある

for(x <- 1 to 100; y <- 1 to 100 if y == x * x) yield (x, y)

これは

flatMap{x => (1 to 100).filter{y => y == x * x}.map{y => (x, y)}}


seq.mkString(tok)でPythonで言うところのtok.join(seq)


xs[i]に相当するコードがxs(i)になる?


Haskellのfoldlに相当するものがある。

xs.foldLeft(0)((sum, n) => sum+n.toInt)


toIntみたいな引数のないメソッドの呼び出しに括弧がないのが多少気に食わないけどいい言語だなぁ。これで静的型ってのがすごいなぁ。
obj.noargmethod _ でそのメソッド自体。obj.add(x, y)の場合も obj.add _でメソッド自体。obj.addは構文エラー。

x /: y means y./:(x) 末尾にコロンがついていると(ユーザ定義の演算子であっても)右辺をレシーバにする

ブロック渡しがあるのいいな。

classとobjectって別個にあるのか。objectはシングルトン。static makeInstanceメソッドが隠されているだけと考えていいのかなぁ

overrideするときには明記する必要がある

class Point(val x :Int, val y :Int){
   ...
}

class Foo extends JFrame("hoge"){
  setSize(100, 100);
}

trait。classからインスタンス生成機能を取り除いたもの。Javaのinterfaceと違って実装を持つ。mix-inにつかう。

implicit def i2str(i :Int) :String = i.toString

がスコープにあれば暗黙の型変換を試みる。

val n = 54321
println(n.endsWith(1))

整数n, 1が両方とも暗黙的に文字列に変換されている。
たとえば1というIntのリテラルがあって、Int自体のクラスがread-onlyだったとしてもInt2MyIntを作ってMyIntでfooというメソッドをつければ1.fooできる。Pythonでは高速化のためにintがread-onlyになっていて1.fooが出来ない。Rubyでは追加できるけども、高速化の妨げになっているはず。静的型なのにクラスに動的にメソッドを追加できたようにみせられるのはすばらしい。

パターンマッチがある

xs match {
  case Array(x, y) => ...
  case Array(x) => ...
}


自分の定義したクラスでも
case class MyTree(l :MyLeaf, r :MyLeaf) ...すればcase MyTree(l, r)できる。
MLのalgebric date type。


case classではないFooでもunapplyってメソッドを定義すれば出来る?


SomeとNoneってのがある。def foo(i :Int) = if (i == 0) Some(1) else None。HaskellのMaybe Int, Just(1), Nothingと同じfooの返り値はOption(Int)


静的に型チェックされるduck typing! Structural typeってのがあるらしい。

type HasName = {def name() :String}

静的にその型がname()を持っていることを確認する。


lazy val x = some_func(...)
xに最初にアクセスするときに評価され、後は再評価されない。サンクを書きやすくするシンタックスシュガー?


パターンマッチングに成功するかどうかだけを確認するidDefinedAt。分散アクターとかで自分が処理できる命令だけ取るとかに使えるのかな。


E4X的なものもある。

val tag = <foo>{x} + {y} = {x + y}</foo>

しかもこのXMLノードに対してパターンマッチをかけられる!!!なんだってー!


generics

val xs :Array[String] = Array("A", "B")
xs(0) = 1 // error!

class Ref[T](private var value :T){
  def unary_! :T = value
  def :=(newValue :T) :Unit ......
}

Higher Kind Generator うわぁclass R[ T[ _ ] ]とかできるのか!何してるんだこれ!

Implicit Parameter 呼び出し側のスコープで定義されていれば渡さなくてもいい

def sum[T](xs :List[T])(implicit adder :Adder[T]) ...
implicit object StrAdder extends Adder[String] { ... }
sum(["a", "b"]) // ここでadderが渡されていないがスコープにList[String]なの
// でAdder[String]を探して、見つかるからそれを使う


Existential type. 時間が短くてよくわからなかったがgenerics的な型で半変とか共変とかでややこしいまわりの話で、Javaの型システムにある問題点を解決しているのだけどもそれだと不便なことがあるので安全に穴をあけるための仕組みだという理解をした。


シンタックスシュガー山盛り、構文複雑、初学者混乱させがち。なんか静的型付けの大前提を守ったままPerl的な哲学で開発したらこんな感じになるのかな、みたいな。


ふう。超駆け足だったけどかなり面白かった。

val x :Array[String] = Array("a", "b", "c)
val y :Array[Any] = x // これは出来ないけどもし出来たとする
// Javaの配列はObject[]にString[]の代入が出来てしまう。
y(0) = 1 // Int <: Anyなのでこれはvalid。ぎゃーxの中に整数が入った!

// 2行目を禁止したくはないが、でもそれに近いことをしたい場合がある。
// 問題になるのは書き込んだときなので書き込ませない型を作ればOK
val z :Array[t] forSome {type T} // 構文こんなのだっけ?