去掉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