Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala中函数文本的分配_Scala - Fatal编程技术网

Scala中函数文本的分配

Scala中函数文本的分配,scala,Scala,我有一个表示销售订单的类: class SalesOrder(val f01:String,val f02:Int,…,f50:Date) fXX字段有多种类型。我面临着创建订单审计跟踪的问题。给定该类的两个实例,我必须确定哪些字段已更改。我提出了以下建议: class SalesOrder(val f01:String, val f02:Int, ..., val f50:Date){ def auditDifferences(that:SalesOrder): List[String]

我有一个表示销售订单的类:

class SalesOrder(val f01:String,val f02:Int,…,f50:Date)

fXX
字段有多种类型。我面临着创建订单审计跟踪的问题。给定该类的两个实例,我必须确定哪些字段已更改。我提出了以下建议:

class SalesOrder(val f01:String, val f02:Int, ..., val f50:Date){

  def auditDifferences(that:SalesOrder): List[String] = {

    def diff[A](fieldName:String, getField: SalesOrder => A) =
      if(getField(this) != getField(that)) Some(fieldName) else None

    val diffList = diff("f01", _.f01) :: diff("f02", _.f02) :: ...
                :: diff("f50", _.f50) :: Nil

    diffList.flatten
  }    
}
我想知道编译器对所有的
\uux.fXX
函数做了什么:它们是只实例化一次(静态地),并且可以被我的类的所有实例共享,还是每次我创建类的实例时都实例化


我担心的是,由于我将使用大量SalesOrder实例,它可能会产生大量垃圾。我应该使用不同的方法吗?

是的,这会创建50个短期函数。我认为你不应该担心,除非你有明显的证据表明这会导致你的案件出现性能问题

但我会定义一个方法,将
saleorder
转换为
Map[String,Any]
,然后您就可以

trait SalesOrder {
  def fields: Map[String, Any]
}
def diff(a: SalesOrder, b: SalesOrder): Iterable[String] = {
  val af = a.fields
  val bf = b.fields 
  af.collect { case (key, value) if bf(key) != value => key }
}
如果字段名实际上只是增量数字,则可以简化

trait SalesOrder {
  def fields: Iterable[Any]
}
def diff(a: SalesOrder, b: SalesOrder): Iterable[String] =
  (a.fields zip b.fields).zipWithIndex.collect { 
    case ((av, bv), idx) if av != bv => f"f${idx + 1}%02d"
  }

解决这个问题的一个干净的方法是使用标准库的。例如:

class SalesOrder(val f01: String, val f02: Int, val f03: Char) {
  def diff(that: SalesOrder) = SalesOrder.fieldOrderings.collect {
    case (name, ord) if !ord.equiv(this, that) => name
  }
}

object SalesOrder {
  val fieldOrderings: List[(String, Ordering[SalesOrder])] = List(
    "f01" -> Ordering.by(_.f01),
    "f02" -> Ordering.by(_.f02),
    "f03" -> Ordering.by(_.f03)
  )
}
然后:

scala> val orderA = new SalesOrder("a", 1, 'a')
orderA: SalesOrder = SalesOrder@5827384f

scala> val orderB = new SalesOrder("b", 1, 'b')
orderB: SalesOrder = SalesOrder@3bf2e1c7

scala> orderA diff orderB
res0: List[String] = List(f01, f03)

几乎可以肯定的是,您不必担心原始配方的性能,但由于不相关的原因,这个版本(可以说)更好。

谢谢。字段具有真实名称。fXX只是一种简化。虽然使用
Map[String,Any]
解决了分配问题,但我认为它有失去类型安全性的缺点:我无法确保分配给它们的值是正确的类型。我想我更希望有一个可以放置所有这些函数的对象,映射只是辅助的,而不是取代常规的getter方法。对于equals操作,
Any
是否来自映射并不重要。基本上,我想说的是,如果您首先将所有字段值收集到某个序列中,那么您可以将它们与一个闭包(而不是50个闭包)进行比较。您还可以担心创建
一些
对象,或者将字段更改存储在
列表中。或者,如果您必须为
n
销售订单调用
diff
n-1
次,您将如何重建审计跟踪。如果遇到性能问题,您现在编写的方法将为优化留下机会。我对“不相关的原因”感到好奇:-)使用
排序比使用
比较不平等更好=