假设您正在编写一个规范化字符串的类。该类有许多配置标志。例如:
val makeLowerCase: Boolean = true
val removeVowels: Boolean = false
val dropFirstCharacter: Boolean = true
如果我正在编写可变代码,我会为normalize
方法编写以下内容。
def normalize(string: String) = {
var s = string
if (makeLowerCase) {
s = s.toLowerCase
}
if (removeVowels) {
s = s.replaceAll("[aeiou]", "")
}
if (dropFirstCharacter) {
s = s.drop(1)
}
s
}
是否有一种干净简单的方法来编写这些没有变异的方法?嵌套条件变得非常讨厌。我可以创建一个String=>String
lambdas列表,根据配置过滤它,然后通过它折叠字符串,但我希望有更容易的东西。
答案 0 :(得分:6)
最好的办法是定义自己的方法:
class ConditionalMapper[A](a: A) {
def changeCheck(p: A => Boolean)(f: A => A) = if (p(a)) f(a) else a
def changeIf(b: Boolean)(f: A => A) = if (b) f(a) else a
}
implicit def conditionally_change_anything[A](a: A) = new ConditionalMapper(a)
现在你把这些东西连在一起写下来:
class Normer(makeLC: Boolean, remVowel: Boolean, dropFirst: Boolean) {
def normalize(s: String) = {
s.changeIf(makeLC) { _.toLowerCase }
.changeIf(remVowel) { _.replaceAll("[aeiou]","") }
.changeIf(dropFirst){ _.substring(1) }
}
}
这给了你:
scala> val norm = new Normer(true,false,true)
norm: Normer = Normer@2098746b
scala> norm.normalize("The Quick Brown Fox Jumps Over The Lazy Dog")
res1: String = he quick brown fox jumps over the lazy dog
那就是说,可变解决方案也不错 - 只需将它保持在一个小块中就可以了。当你让可变性逃到野外时,这主要是一个问题。 (其中“野性”的意思是“在你的方法之外,或在任何方法之内,而不是少数几行”。)
答案 1 :(得分:4)
如果您使用scalaz |>
运算符或在实用程序类中定义了类似运算符,则可以执行以下操作:
case class N(
makeLowerCase: Boolean = true,
removeVowels: Boolean = false,
dropFirstCharacter: Boolean = true) {
def normalize(string: String) = (
string
|> (s => if (makeLowerCase) s.toLowerCase else s)
|> (s => if (removeVowels) s.replaceAll("[aeiou]", "") else s)
|> (s => if (dropFirstCharacter) s.drop(1) else s)
)
}
N(removeVowels=true).normalize("DDABCUI")
// res1: String = dbc