去掉Scala中可变的局部变量

去掉Scala中可变的局部变量,scala,Scala,我定义了一个具有以下签名的筛选器方法 def filterAcc(predicate: Element => Boolean, acc: ElementSet): ElementSet = { // filter elements which satisfy the predicate into new Set var newAccumulator = if (predicate(this.value) acc.add(this.value) else acc newAccum

我定义了一个具有以下签名的筛选器方法

def filterAcc(predicate: Element => Boolean, acc: ElementSet): ElementSet = {
  // filter elements which satisfy the predicate into new Set
  var newAccumulator = if (predicate(this.value) acc.add(this.value) else acc
  newAccumulator = this.leftChild(predicate, newAccumulator)
  this.rightChild(predicate, newAccumulator)
}
IDE抱怨如下

Avoid Mutable local variables
我的用例如下

Avoid Mutable local variables
  • add
    方法在添加元素后返回一个新集合,因此我必须将其接收到另一个变量中
  • 类似地,
    leftChild.filterAcc
    将返回新的累加器作为新元素集
  • 因此,每次调用
    add
    filterAcc
    时,我都必须接收一个新变量。写这段代码的正确方法是什么


    你可以假设逻辑是正确的。我只是想深入研究面向Scala的代码流,所以想知道编写这种类型的逻辑而不出现警告/错误的最佳实践。

    显然没有必要使
    newacculator
    可变。只需定义一个新的不可变的
    val

      val newAccumulator = if (predicate(this.value) acc.add(this.value) else acc
      val newerAccumulator = this.leftChild(predicate, newAccumulator)
      this.rightChild(predicate, newerAccumulator)
    

    事实上,代码可以进一步压缩:但我选择不这样做是为了允许当前的可读性级别。

    显然没有必要使
    newacculator
    可变。只需定义一个新的不可变的
    val

      val newAccumulator = if (predicate(this.value) acc.add(this.value) else acc
      val newerAccumulator = this.leftChild(predicate, newAccumulator)
      this.rightChild(predicate, newerAccumulator)
    

    事实上,代码可以进一步压缩:但我选择不这样做是为了允许您当前的可读性水平。

    您可以简单地使用以下方法来避免
    var

    def filterAcc(predicate: Element => Boolean, acc: ElementSet): ElementSet = {
        this.rightChild(predicate, this.leftChild(predicate, applyPredicate(predicate, acc)))
      }
    
    def applyPredicate(predicate: Element => Boolean, acc: ElementSet) = if (predicate(this.value) acc.add(this.value) else acc
    

    您可以简单地使用以下方法来避免
    var

    def filterAcc(predicate: Element => Boolean, acc: ElementSet): ElementSet = {
        this.rightChild(predicate, this.leftChild(predicate, applyPredicate(predicate, acc)))
      }
    
    def applyPredicate(predicate: Element => Boolean, acc: ElementSet) = if (predicate(this.value) acc.add(this.value) else acc
    

    在这种情况下,我根本不会使用命名val调用
    leftChild
    @javadba的答案更接近您的原始答案,但更具可读性是一个意见问题:

    def filterAcc(predicate: Element => Boolean, acc: ElementSet): ElementSet = {
      // filter elements which satisfy the predicate into new Set
      val newAccumulator = if (predicate(this.value) acc.add(this.value) else acc
      this.rightChild(predicate, this.leftChild(predicate, newAccumulator))
    }
    

    在这种情况下,我根本不会使用命名val调用
    leftChild
    @javadba的答案更接近您的原始答案,但更具可读性是一个意见问题:

    def filterAcc(predicate: Element => Boolean, acc: ElementSet): ElementSet = {
      // filter elements which satisfy the predicate into new Set
      val newAccumulator = if (predicate(this.value) acc.add(this.value) else acc
      this.rightChild(predicate, this.leftChild(predicate, newAccumulator))
    }
    

    这正是我想做的,下一步我就做了。我不想失去“代码可读性”,所以我认为这是一个很好的解决方案。我会等一会儿接受这个。感谢有时,让这种解决方案难看的不是结构,而是命名。我会尝试用更抽象的语义替换newacculator和neweraccculator。新的和更新的谈论你的想法,它是一个不变的集合和他们存在的时间。在我看来,更有趣的是,每一个都包含了实现细节之外的内容。也许像“withCurrent”和“withLeft”之类的东西。你可能会想出更好的办法。@Det OP/问题是关于结构而不是语义的:回答是这样写的,直接响应他们的请求。当然,他不会在最后的代码中使用这种命名约定。@javadba不知道未知的人自然会做什么或不做什么。特别是如果我们认为这不是一个私人讨论,而是一个公开的讨论,可能有成千上万的人阅读。在可读性方面,我也认为值得加上这句话。这正是我的想法,我下一步就是这么做的。我不想失去“代码可读性”,所以我认为这是一个很好的解决方案。我会等一会儿接受这个。感谢有时,让这种解决方案难看的不是结构,而是命名。我会尝试用更抽象的语义替换newacculator和neweraccculator。新的和更新的谈论你的想法,它是一个不变的集合和他们存在的时间。在我看来,更有趣的是,每一个都包含了实现细节之外的内容。也许像“withCurrent”和“withLeft”之类的东西。你可能会想出更好的办法。@Det OP/问题是关于结构而不是语义的:回答是这样写的,直接响应他们的请求。当然,他不会在最后的代码中使用这种命名约定。@javadba不知道未知的人自然会做什么或不做什么。特别是如果我们认为这不是一个私人讨论,而是一个公开的讨论,可能有成千上万的人阅读。在可读性方面,我也认为值得加上这句话。这不起作用,
    acc
    不在
    applyPredicate
    Ahh的范围内,对不起。我只是复制粘贴的
    if
    子句。现在已更正。现在您在调用
    applyPredicate
    时未通过
    acc
    ,这不起作用,
    acc
    不在
    applyPredicate
    的范围内,抱歉。我只是复制粘贴的
    if
    子句。现在已更正。现在您在调用
    applyPredicate