考慮下面的代碼:斯卡拉鑽營/諧音打造功能過濾列表
case class Config(
addThree: Boolean = true,
halve: Boolean = true,
timesFive: Boolean = true
)
def doOps(num: Integer, config: Config): Integer = {
var result: Integer = num
if (config.addThree) {
result += 3
}
if (config.halve) {
result /= 2
}
if (config.timesFive) {
result *= 5
}
result
}
val config = Config(true,false,true)
println(doOps(20, config))
println(doOps(10, config))
我想用一個更高效,更地道的構造來代替難看doOps方法。具體來說,我想建立一個功能鏈,只根據所使用的特定配置執行所需的轉換。我知道我可能想創建一些可以將Integer傳入的部分應用函數,但是我正在爲如何以有效的方式實現這一目標畫一個空白。
我特別想避免doOps中的if語句,我希望得到的結構只是一個調用鏈中下一個函數的鏈而不檢查有條件的第一個。
生成的代碼,我想會是這個樣子:
case class Config(
addThree: Boolean = true,
halve: Boolean = true,
timesFive: Boolean = true
)
def buildDoOps(config: Config) = ???
val config = Config(true,false,true)
def doOps1 = buildDoOps(config)
println(doOps1(20))
println(doOps1(10))
非常有趣的構造。這可能是不重要的(基於scala/jvm如何最終優化代碼),但似乎執行路徑包括執行'identity'函數而不是完全跳過執行(就好像Seq從未包含該步驟一樣) 。我明確地想避免使用'if'語句,我想知道'identity'的額外遞歸是如何影響實際執行路徑的。我想'Seq'可以首先被過濾掉,以在'foldLeft'之前刪除'identity'調用,但我不確定這是否實際上最終會變得多餘。 – 2013-02-15 18:32:25
@ConnieDobbs:使用Option [Int => Int]'和'flatten'來查看'funChain'的第二個版本,並避免'identity'。 – 2013-02-15 18:33:40
感謝Thomasz,您添加了最新編輯的'Option' /'flatten'組合,我認爲避免了額外的'identity'函數調用的任何(可能/理論上的)低效率,同時(IMO)實際上提高了可讀性。 – 2013-02-15 21:16:06