首先所有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) }
沒有留言:
張貼留言