Пример из книжки Степанова. Египетское умножение. Я реализовал для целых чисел (Int)
def half(a:Int) : Int = a / 2
def half(a:BigInt) : BigInt = a / 2
def odd(a:Int) : Boolean = a % 2 == 1
def odd(a:BigInt) : Boolean = a % 2 == 1
def mult_acc4(n:Int, a:Int, r:Int = 0) : Int = (odd(n), n) match {
case (true, 1) => r + a
case (true, _) => mult_acc4(half(n), a + a, r + a)
case (_,_) => mult_acc4(half(n), a + a, r)
}
Потом был интерес сделать в BigInt чтобы Египетское умножение себя хоть как-то показало на длинных числах.
def mult_acc5(n:BigInt, a:BigInt, r:BigInt = 0) : BigInt = (odd(n), n) match {
case (true, 1) => r + a
case (true, _) => mult_acc5(half(n), a + a, r + a)
case (_,_) => mult_acc5(half(n), a + a, r)
}
Здесь пришлось сделать еще две реализации для проверки нечетных odd() и для деления на 2 half().
После этого я стал искать обобщенную реализацию. Сделал интерфейс числа которое складывает и делит и прочее.
И получается что писанины у меня стало от этого только больше. И баги ООП - как тушение пожара. Фиксишь один - лезет
следующих два.
trait PolyNum[T] {
def +(x:T) : T
def half : T
def odd : Boolean
def one : T
}
// illegal trait inheritance: superclass AnyVal does not derive from trait PolyNum's superclass Object
case class X(v:BigInt) extends AnyVal with PolyNum[BigInt] {
override def +(x:BigInt) : BigInt = v + x
override def odd : Boolean = v % 2 == 1
override def half : BigInt = v / 2
override def one : BigInt = BigInt(1)
}
// TODO: Fix
def mult_acc6[T](n:PolyNum[T], a:PolyNum[T], r:PolyNum[T]) : PolyNum[T] = (n.odd, n) match {
case (true, n.one) => r + a
case (true, _) => mult_acc6(n.half, a + a, r + a)
case (_,_) => mult_acc6(n.half, a + a, r)
}
Чувсвтую что ошибаюсь. Вот где?
Как красиво и изящно обобщить операции над целым и над BigInt?