【问题标题】:Scala -- apply unapply rulesScala——应用不适用规则
【发布时间】:2013-11-08 14:16:52
【问题描述】:

我想知道 Scala 中是否有规则或“最佳实践”来覆盖应用/取消应用。我对持有以下属性是否是一个好主意特别感兴趣:

给定案例类 C(x: T),对于所有 x,Some(x) == C.unapply(C.apply(x))。

我问的原因是因为我计划使用以下代码来确保 BigDecimal 的精度为 16。

class BoundedBigDecimal(private val bd: BigDecimal) extends Proxy {
  val self: BigDecimal = bd setScale (BoundedBigDecimal.PRECISION)
}

object BoundedBigDecimal {
  val PRECISION = 16
  def apply(bd: BigDecimal) = new BoundedBigDecimal(bd)
  def unapply(bbd: BoundedBigDecimal) = Some(bbd.self)
}

如您所见,该属性不一定在这里成立。

是吗:

1) 理想情况下应该在一般情况下强制执行的属性?

2) 做我想做的事情的正确方法?

谢谢!

【问题讨论】:

    标签: scala case-class


    【解决方案1】:

    我更喜欢使用“标记类型”:

    type Tagged[U] = { type Tag = U }
    type @@[T, U] = T with Tagged[U]
    
    trait Bounded
    
    object BoundedBigDecimal {
      val PRECISION = 16
    
      def apply(bd: BigDecimal) = 
        (bd setScale PRECISION).asInstanceOf[BigDecimal @@ Bounded]
    
      def unapply(bbd: BigDecimal @@ Bounded) = 
        Some(bbd)
    
      implicit def toBD(bd: BigDecimal): BigDecimal @@ Bounded = 
        BoundedBigDecimal(bd)
    }
    

    使用herehere 对标记类型及其好处进行了很好的描述。

    【讨论】:

    • 但与 Haskell 中的 newtypes 不同,Scala 中的标记类型不会阻止您意外添加两个不同标记的 BigDecimals,如第一篇文章所述。
    【解决方案2】:

    为什么不使用:

    def testPrecision(bd:BigDecimal):Boolean = 
    db.scale == 16
    

    还是我错过了什么?

    编辑:更新到 ReducePrecision:

    def boundedBD(bd:BigDecimal):BigDecimal =
    {   
       val maxPrecision = 16
       bd.scale match {
       case x if x > maxPrecision  => bd setScale  maxPrecision 
       case _ => bd
    }
    
    
    }
    

    【讨论】:

    • 感谢您的回答!实际上,重点不是测试精度是否为 16,重点是强制每个 BigDecimal 数的精度最高为 16。这就是为什么我定义这个 BoundedBigDecimal 以便 BoundedBigDecimal(1.111111111111111111111) 变为 1.1111111111111111。抱歉,如果我的问题不清楚...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-21
    • 2013-07-03
    • 2018-01-19
    • 2018-04-02
    • 1970-01-01
    相关资源
    最近更新 更多