2011-03-08 113 views
1

我的直覺說,下面的代碼可以縮短,但我不知道如何。你可以幫我嗎?縮短我的代碼

def asGraphingFunction[A : Numeric, B : Numeric](f: PartialFunction[A, B]): Double => Double = { 
    val (numericA, numericB) = (implicitly[Numeric[A]], implicitly[Numeric[B]]) 
    (x: Double) => { 
    val xa: A = numericA.fromInt(x.toInt) 
    if(f.isDefinedAt(xa)) 
     numericB.toDouble(f(xa)) 
    else 
     0.0 
    } 
} 
+0

我不知道斯卡拉,但是有什麼特別的理由說明爲什麼你想讓代碼「更短」嗎?它對我來說似乎相當易讀,是不是比代碼行數更重要? –

+0

@ michael - 他們齊頭並進,看到我對這個 –

回答

1

這個怎麼樣?:

import scala.{ PartialFunction => PF } 
def asGraphingFunction[A : Numeric, B : Numeric](f: PF[A, B]): Double => Double = { 
    val pf1: PF[Double,A  ] = { case d => numericA.fromInt(d.toInt) } 
    val pf2: PF[B  ,Double] = { case b => numericB.toDouble(b) } 
    val pf3: PF[Double,Double] = { case _ => 0 } 
    pf1 andThen f andThen pf2 orElse pf3 
} 

爲不短,但也許更清晰?任何意見?

7

兩個小技巧在這裏:

  1. ,因爲你需要命名Numeric情況下,它更容易只是去糖背景下界定爲隱性參數

  2. 使用PartialFunction#liftPartialFunction[A,B]轉換爲A => Option[B]

然後刪除樣板和...瞧!

def asGraphingFunction[A, B](f: PartialFunction[A, B]) 
(implicit numA: Numeric[A], numB: Numeric[B]) = 
    (x: Double) => f.lift(numA fromInt x.toInt) map (numB.toDouble) getOrElse 0.0 

如果使用正管道操作符(無論是從scalaz,或定義here),那麼就可以變得更加清晰:

def asGraphingFunction[A, B](f: PartialFunction[A, B]) 
(implicit numA: Numeric[A], numB: Numeric[B]) = 
    (x: Double) => (numA fromInt x.toInt) |> f.lift map (numB.toDouble) getOrElse 0.0 

更新

正如你只轉換整數/雙打,你根本不需要Numeric,你可以通過java.util.Number做任何事情,在這個過程中丟棄類型參數:

def asGraphingFunction(f: PartialFunction[Number, _ <: Number]) = 
    (x: Number) => f.lift(x.intValue) map (_.doubleValue) getOrElse 0.0 
+0

的回答很好!比我的方法更好。投票! :d –