2011-09-01 scalaの抽象型について考えてみる
scalaの抽象型について考えてみる
fmfm つまり Scalaのimportはjavaのimportより強力で、instance.memberみたいなことを書くと、その今テキスト中でmemberに対してアクセスできる、VBとかのwithみたいな機能がありますよ、と。 #scalajp *Tw*
@seraphr そうですね。加えて、Scalaは「オブジェクトの」メンバとして型(抽象型を含む)を持てる事が強力ですね。14章の例は、それを端的に示しているものです。
2011-09-01 00:03:09 via web to @seraphr
@kmizu fmfm ただ型をオブジェクト(インスタンス)のメンバとして持てるとしても、コンパイル時に静的な型を決定しなければならない以上、それを用いたポリモフィズム的なのは無理そうで、完全修飾名を書かなくていいとかそういう記述上の嬉しさ以上のことが想像つかないですね *Tw*
2011-09-01 00:35:12 via Twit for Windows to @kmizu
@seraphr この辺の機構を利用することで、複数のクラスの間で相互作用があり、それらの「クラスのグループ」のようなものをうまくモジュール化できる、ということがScalaチームの発表スライド等で述べられています。
2011-09-01 00:59:38 via web to @seraphr
@kmizu うーん。 そういう利用方法の範囲だと、初めて抽象型を見たときにも思ったんですけど、Genericsで出来ることと何が違うんだろうなー、という疑問に落ち着いちゃうんですかね。 型の所属関係を明示することで、更に整理された状態にできるとかそういう話なのかなぁ *Tw*
2011-09-01 01:28:29 via Twit for Windows to @kmizu
みたいなことを言っていたら、Expression Problemを解決するという文脈で、以下のコードを書いてもらえた。
https://gist.github.com/1184933
これを、Genericsと比較するために、Generics + 自分型注釈なコードを書いてみた。
trait VisitorsBaseGenerics { self => trait Node[V <: Visitor[V]] { def accept(v: V) } case class Add[V <: Visitor[V]](l: Node[V], r: Node[V]) extends Node[V] { def accept(v: V) { v.visit(this) } } case class Sub[V <: Visitor[V]](l: Node[V], r: Node[V]) extends Node[V] { def accept(v: V) { v.visit(this) } } case class Value[V <: Visitor[V]](value: Int) extends Node[V] { def accept(v: V) { v.visit(this) } } trait Visitor[V <: Visitor[V]] { self: V => def visit(node: Add[V]) { println("Add!") node.l.accept(this) node.r.accept(this) } def visit(node: Sub[V]) { println("Sub!") node.l.accept(this) node.r.accept(this) } def visit(node: Value[V]) { println("Value: " + node.value) } } } class VisitorsPlusGenerics extends VisitorsBaseGenerics { case class Mul[V <: Visitor[V]](l: Node[V], r: Node[V]) extends Node[V] { def accept(v: V) { v.visit(this) } } case class Div[V <: Visitor[V]](l: Node[V], r: Node[V]) extends Node[V] { def accept(v: V) { v.visit(this) } } class Visitor[V <: Visitor[V]] extends super.Visitor[V] { self: V => def visit(node: Mul[V]) { println("Mul") node.l.accept(this) node.r.accept(this) } def visit(node: Div[V]) { println("Div") node.l.accept(this) node.r.accept(this) } } } object VisitorGenericsMain { val mVisitorContainer = new VisitorsPlusGenerics import mVisitorContainer._ class UseVisitor extends Visitor[UseVisitor] def main(args: Array[String]) { val v = new UseVisitor Add(Value(1), Value(2)).accept(v) Sub(Value(1), Value(2)).accept(v) Mul(Value(1), Value(2)).accept(v) Div(Value(1), Value(2)).accept(v) } }
実際に使う場合&拡張について考えるため、VisitorsPlusGenericsでは型を確定させないようにしておいた。
自分型注釈についてよくわかってないのは内緒。 あとでドキュメント読む。
時間がないので、とりあえずここまで。
こういう、自己参照(自己言及?)するGenericsコードはたまに書くことがあるんだけど、単純な記述量的な嬉しさは感じた。 それ以外についてはまたあとで考えてみる。