2013-06-26 29 views
3

的和平我無法弄清楚如何才能讓下面的代碼是不變的:使得代碼不變

def function123(str: String, mapVal: Map[String, String]) = { 
    var str1 = str 
    mapVal.keySet.foreach({x => 
     str1 = str1.replaceAll(/*some pattern involving x*/, mapVal.get(x).get)}) 
    str1 
} 

我懷疑我會使用foldLeft或參數蓄能器嵌套的方法,但這些只是我的想法。

那麼我該怎麼做?

+1

通常你使對象不可改變,從你的兩個參數中,字符串已經是不可變的並且Map,你可以每次都複製並返回一個新的地圖 – Sap

回答

5

foldLeft

這裏有一個循環。

有副作用的環不可改變的版本是foldLeft與下一狀態創造更換了所有的副作用:

val result = mapVal.foldLeft(str){case (state, (key, value)) => 
    state.replaceAll(/*some pattern involving key*/, value) 
} 

要在一成不變的環境中工作循環的每個迭代應該返回值,並採取以前的結果迭代作爲參數。這正是foldLeft

遞歸

另一個解決方案是遞歸的方法。你應該提取循環迭代方法,使這個方法調用下一次迭代中底:

def function123(str: String, mapVal: Map[String, String]) = { 
    @tailrec def loop(state: String, pairs: List[(String, String)]): String = pairs match { 
    case Nil => state 
    case (key, value) :: tail => 
     val nextState = state.replaceAll(/*some pattern involving key*/, value) 
     loop(nextState, tail) 
    } 
    loop(str, mapVal.toList) 
} 

易變環 - >不變

使代碼與可變循環是不可改變的,你應該提取所有值隱式地涉及到循環內的變化到某種狀態(單個狀態對象爲foldLeft或遞歸方法的一堆參數),然後在每次迭代結束時基於前一個產生新狀態。

+0

'帶副作用的循環的不可變版本是foldLeft,所有副作用都封裝在state ' - 你的意思是什麼副作用? –

+0

@MariusKavansky:查看最新的更新。我的意思是所有的副作用。所有涉及重新分配任何值的操作。任何'var'的重新分配或可變對象的突變。請注意,「I/O」和消息發送是帶有副作用的操作。 – senia

+0

抱歉,目前尚不清楚。你的第一個例子中沒有「var」,因此也沒有任何副作用。他們在哪? –