在scala中,我有以下代码:
def isDifferentGroup(artifact2: DefaultArtifact) = getArtifact(artifact1Id).getGroupId != artifact2.getGroupId
val artifacts = getArtifacts().filter(isSameGroup)
函数isDifferentGroup
正在访问外部String变量artifactId
(闭包)。
我想避免为列表中的每个项目计算getArtifact(artifactId)
。
我可以这样做:
val artifact1: DefaultArtifact = getArtifact(artifact1Id)
def isDifferentGroup(artifact2: DefaultArtifact) = artifact1.getGroupId != artifact2.getGroupId
val artifacts = getArtifacts().filter(isSameGroup)
但是,我们在函数artifact1
之外创建变量isDifferentGroup
,这很难看,因为此变量仅在函数isDifferentGroup
内使用。
如何解决?
一种可能性是使部分功能如下:
def isDifferentGroup(artifact1: DefaultArtifact)(artifact2: DefaultArtifact) = artifact1.getGroupId != artifact2.getGroupId
val artifacts = getArtifacts().filter(isDifferentGroup(getArtifact(artifact1Id)))
但是,我必须将代码getArtifact(artifactId)
移到isDifferentGroup
函数之外,我不希望这样。
如何解决?
答案 0 :(得分:2)
每次调用函数时都会对函数体中处理的所有内容进行求值,因此您无法分辨它的一部分是否会被静态评估和共享(无需使用某种外部缓存)。因此,您必须将函数体与要预先评估的值分开,并在函数内部使用。
但是,您可以将这些值括在一个块中,以便形成一个紧凑的块。我能想到的最好的事情是使用函数类型声明val
,例如
val isDifferentGroup: DefaultArtifact => Boolean = {
val gid = getArtifact(artifact1Id).getGroupId
(artifact2: DefaultArtifact) => {
(gid != artifact2.getGroupId)
}
}
这样,您可以在主val
块(此处为gid
)中明确说明静态评估哪个部分,以及响应artifact2
参数评估哪个部分。您可以像调用方法一样调用isDifferentGroup
:
println(isDifferentGroup(someArtifact))
这基本上只是创建像
这样的封装类的另一种方式val isDifferentGroup: DefaultArtifact => Boolean =
new Function1[DefaultArtifact,Boolean] {
val gid = getArtifact(artifact1Id).getGroupId
override def apply(artifact2: DefaultArtifact): Boolean =
(gid != artifact2.getGroupId);
}
您甚至可以将其声明为lazy val
,在这种情况下,gid
最多只需 ,这是第一次调用该函数。
答案 1 :(得分:0)
为什么不创建一个类来封装(私有)值和功能?
这段代码可能无法编译,只是为了说明它:
class Artifact(artifact1Id: Id) {
private val artifact1: DefaultArtifact = getArtifact(artifact1Id)
def isDifferentGroup(artifact2: DefaultArtifact) =
artifact1.getGroupId != artifact2.getGroupId
}