Scala функциональное программирование гимнастика - PullRequest
10 голосов
/ 10 ноября 2010

Я пытаюсь сделать следующее, используя как можно меньше кода и как можно более функционально:

def restrict(floor : Option[Double], cap : Option[Double], amt : Double) : Double

Очевидно следующие работы:

= (floor -> cap) match {
    case (None, None)       => amt
    case (Some(f), None)    => f max amt 
    case (None, Some(c))     => c min amt
    case (Some(f), Some(c)) => (f max amt) min c
  }

Я действительно надеялся на что-то более элегантное и приму использование библиотеки Scalaz ! Можно предположить, что верно следующее :

floor.forall( f => cap.forall( _ > f))
<Ч />

Если кому-то интересно, вот тестовый код :

object Comparisons {
  sealed trait Cf {
    def restrict(floor: Option[Double], cap: Option[Double], amt: Double): Double
  }

  def main(args: Array[String]) {
    val cf : Cf = //TODO - your impl here!
    def runtest(floor: Option[Double], cap: Option[Double], amt: Double, exp : Double) : Unit = {
      val ans = cf.restrict(floor, cap, amt)
      println("floor=%s, cap=%s, amt=%s === %s (%s) : %s".format(floor, cap, amt, ans, exp, if (ans == exp) "PASSED" else "FAILED"))
    }
    runtest(Some(3), Some(5), 2, 3)
    runtest(Some(3), Some(5), 3, 3)
    runtest(Some(3), Some(5), 4, 4)
    runtest(Some(3), Some(5), 5, 5)
    runtest(Some(3), Some(5), 6, 5)

    runtest(Some(3), None, 2, 3)
    runtest(Some(3), None, 3, 3)
    runtest(Some(3), None, 4, 4)
    runtest(Some(3), None, 5, 5)
    runtest(Some(3), None, 6, 6)

    runtest(None, Some(5), 2, 2)
    runtest(None, Some(5), 3, 3)
    runtest(None, Some(5), 4, 4)
    runtest(None, Some(5), 5, 5)
    runtest(None, Some(5), 6, 5)

    runtest(None, None, 2, 2)
    runtest(None, None, 3, 3)
    runtest(None, None, 4, 4)
    runtest(None, None, 5, 5)
    runtest(None, None, 6, 6)
  }
}

Ответы [ 13 ]

0 голосов
/ 06 августа 2011

Мне больше всего нравится первоначальное решение с использованием регистра, кроме того факта, что я не понял, что amt означает amount (в Германии «amt» означает «офис»), и я знал только 1003 * как то, что я ношу на голове ...

Теперь вот действительно скучное решение, использующее внутренний метод:

def restrict(floor : Option[Double], cap : Option[Double], amt : Double) : Double = {
  def restrict (floor: Double, cap: Double, amt: Double) =
    (floor max amt) min cap
  var f = floor.getOrElse (amt)            
  val c = cap.getOrElse (amt)   
  restrict (f, c, amt) 
}
0 голосов
/ 18 апреля 2011

Простое решение с простым Scala и анонимной лямбдой, без каких-либо отображений, сгибов, Double. {Min / Max} Value и т. Д .:

def restrict(floor : Option[Double], cap : Option[Double], amt : Double) : Double =
  ((x:Double) => x min cap.getOrElse(x))(amt max floor.getOrElse(amt))
0 голосов
/ 15 ноября 2010

Я добавляю еще один ответ, который был вдохновлен как retronym , так и Debilski - в основном это означает преобразование кепки и пола в функции (Double => Double, если они есть), а затем складывает через них функцию тождества с составом:

def restrict(floor: Option[Double], cap: Option[Double], amt: Double) = {
  (identity[Double] _ /: List(floor.map(f => (_: Double) max f), cap.map(c => (_: Double) min c)).flatten){ _ andThen _ }(amt)
}
...