LoginSignup
1
1

More than 5 years have passed since last update.

Scalaに代数型(datatype)を実装する その1

Last updated at Posted at 2013-07-13

代数型(datatype)を実装したい

今まで、Scalaのソースコードを読んできたのは、
case class の文法が使い勝手が悪いので、
SMLのようなdatatypeを導入したいと思ったからです。

datatypeを実装するとなると、classと同レベルの位置(構文解析上)に実装することになります。

Parsers.scala をみてみると、トップレベルで宣言されたclassと、
それ以外で宣言されたclassとでは多少扱いが違うようです。
トップレベルの処理は、メソッドtopStatSeq()からメソッドtopLevelTmplDefを呼び出して処理されています。
一方、それ以外の場合には、メソッドdefOrDcl()からメソッドtmplDef()を呼び出して処理されています。

そこで、datatypeの実装方法もトップレベルとそれ以外にわけて考えることにします。

文法を決める

まずは、実装したい構文の文法を決定しなければなりません。
参考にする文法は、Soopyデータタイプ宣言にします。

構文の例をあげていきます。

構文
 datatype Week = Mon | Tue | Wed | Thi | Fri | Sat | Sun

これをパターンマッチで次のように使いたいわけです。

使い方
val day: Week = Wed()
day match {
    case Mon() => "月曜日"
    case Tue() => "火曜日"
    case Wed() => "水曜日"
    case Thi() => "木曜日"
    case Fri() => "金曜日"
    case Sat() => "土曜日"
    case Sun() => "日曜日"
}

これが出来れば、case classを使うより簡単に書けるようになります。

さらに、次のようにメソッドも使えるようにしたいと思っています。

構文
datatype Week {
    def isWorkday: Boolean = true
    def isHoliday(): Boolean = ! isWorkday
  }
= Mon
| Tue
| Wed
| Thi
| Fri
| Sat {
    override def isWorkday = false
  }
| Sun {
    override def isWorkday = false
  }
使い方
val day1 = Mon()
val day2 = Sun()
println( day1.isWorkday )
println( day1.isHoliday )
println( day2.isWorkday )
println( day2.isHoliday )

もちろん、コンストラクタは引数を取る事も可能にしたいです。

構文
datatype Fig =
  Rect(val x: Double, val y: Double){
    def area(): Double = x * y
  }
| Circle(val r: Double){
    val pi = 3.14
    def area(): Double = r * r * pi
  }
使い方
val r = Rect(5, 7)
val c = Circle(8)
val rect_area = r.area()
val circle_area = c.area()

実装方法

Scalaにdatatypeを実装する方法を考えてみましょう。

上で書いたように、case classの文法が冗長なのをなんとかしたくて考えたのが、datatypeになります。実際にできることも、case classとほぼ同じです。
なので、ここではdatatypeをcase classに変換することで、その機能を実現しようと思います。

(つづく)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1