I am trying to do the following in as little code as possible and as functionally as possible:
def restrict(floor : Option[Double], cap : Option[Double], amt : D
This is based on Ken Bloom's answer:
sealed trait Constrainer { def constrain(d : Double) : Double }
trait Cap extends Constrainer
trait Floor extends Constrainer
case object NoCap extends Cap { def constrain(d : Double) = d }
case object NoFloor extends Floor { def constrain(d : Double) = d }
implicit def d2cap(d : Double) = new Cap { def constrain(amt : Double) = d min amt }
implicit def d2floor(d : Double) = new Floor { def constrain(amt : Double) = d max amt }
def restrict(amt : Double, cap : Cap = NoCap, floor: Floor = NoFloor) : Double = {
cap.constrain(floor.constrain(amt))
//or (cap.constrain andThen floor.constrain) amt
}
It ends up with writing code like this:
restrict(amt, cap = 5D)
restrict(amt, floor = 0D)
I think that's pretty awesome and doesn't suffer from the problem with Ken's solution (in my opinion), which is that it is a hack!