首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala中函数字面量的分配

Scala中函数字面量的分配
EN

Stack Overflow用户
提问于 2013-07-01 03:57:10
回答 2查看 138关注 0票数 4

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

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

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

代码语言:javascript
复制
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
  }    
}

我想知道编译器如何处理所有的_.fXX函数:它们是只实例化一次(静态地),并且可以被我的类的所有实例共享,还是每次我创建我的类的实例时都实例化它们?

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-07-01 07:35:20

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

代码语言:javascript
复制
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)
  )
}

然后:

代码语言:javascript
复制
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)

几乎可以肯定的是,您不需要担心原始公式的性能,但这个版本(可以说)更好,因为一些无关的原因。

票数 2
EN

Stack Overflow用户

发布于 2013-07-01 04:29:36

是的,这会创建50个短暂的函数。我不认为您应该担心,除非您有明显的证据表明这会导致您的情况下的性能问题。

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

代码语言:javascript
复制
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 }
}

如果字段名确实只是递增的数字,那么您可以简化

代码语言:javascript
复制
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"
  }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17394302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档