code

2016年10月27日 星期四

Scala筆記 12 - Scala as a pure OOL

所謂的pure object oriented language就是所有的value都是object,用這個標準檢視Scala的話,我們可以說Scala是一個pure OOL。

首先所有JVM primitive types都有對應到的Scala classes,而Scala compiler在runtime會將這些Scala class做optimization,例如用32-bit int表示scala.Int。

舉例來說,我們可以用以下的Scala class來表示Boolean type,而且class definition中完全不會出現任何primitive data value

abstract class BooleanX {
  def ifThenElse[T] (t: => T, e: => T) : T
  def && (x: => BooleanX): BooleanX = ifThenElse(x, falseX)
  def || (x: => BooleanX): BooleanX = ifThenElse(trueX, x)
  def unary_! : BooleanX = ifThenElse(falseX, trueX)
  def == (x: BooleanX): BooleanX = ifThenElse(x, x.unary_!)
  def != (x: BooleanX): BooleanX = ifThenElse(x.unary_!, x)
}

object trueX extends BooleanX {
  def ifThenElse[T](t: => T, e: => T) = t
}

object falseX extends BooleanX {
  def ifThenElse[T](t: => T, e: => T) = e
}

乍看之下很難懂,首先要知道,我們必須用數學性質也就是function來定義這個BooleanX要怎麼behave。我們知道boolean值的定義就是truth table,事實上就是一堆opertors/functions能產生預期的結果就可以。

所以先定義一個abstract class BooleanX,裡面最關鍵的就是第一個function ifThenElse,因為其他所有operators都是建築於其上所定義,而它隱性地定義trueX和falseX object應該有的反應。

ifThenElse 可以解讀成如果this是trueX,evaluate第一個參數t,否則evaluate第二個參數e。在這個定義下去看BooleanX其他的function定義才能懂。


所以如果我們要加上一個 < operator,其expected outcome建立在這 falseX < trueX 微針,其餘為假的事實上:

def < (x:BooleanX): BooleanX = ifThenElse(falseX, x) //falseX < trueX is fact

以下程式跑起來會是我們預期的結果:

object Main extends App {
  println(trueX < trueX)
  println(trueX < falseX)
  println(falseX < trueX)
  println(falseX < falseX)

}

Test.falseX$@5ebec15
Test.falseX$@5ebec15
Test.trueX$@21bcffb5
Test.falseX$@5ebec15


Pure OO Natural Number

另一個例子是我們可以寫出pure object的自然數:

abstract class Nat {
  def isZero: Boolean = predecessor == null  
  def predecessor: Nat
  def successor: Nat = new Succ(this)
  def + (that: Nat): Nat
  def - (that: Nat): Nat

}

object Zero extends Nat {
  def predecessor: Nat = null  
  def + (that: Nat): Nat = that
  def - (that: Nat): Nat = throw new NoSuchElementException()

  override def toString: String = "0"
}

class Succ(n: Nat) extends Nat { //this is the successor of n
  def predecessor: Nat = n

  def + (that: Nat): Nat = new Succ(n + that)

  def - (that: Nat): Nat = if (that.isZero) this else (predecessor - that.predecessor)

  override def toString: String = {
    def helper(amount:Nat, acc:Int) : String = {
      if (amount.isZero) acc.toString
      else helper(amount.predecessor, acc+1)
    }
    helper(this, 0)
  }
}


object Main extends App {

  val one =  new Succ(Zero)
  val two = new Succ(one)
  val ten = two + two + two + two + two  
  val five = ten - two - one - two
  println(Zero)
  println(one)
  println(ten)
  println(five)

}


沒有留言:

張貼留言