2015-05-21 51 views
0

具有不同的價值類型的地圖結合我有工作了下面的代碼:如何在斯卡拉

case class Step() { 
    def bindings(): Map[String, Any] = ??? 
} 

class Builder { 
    private val globalBindings = scala.collection.mutable.HashMap.empty[String, Any] 
    private val steps = scala.collection.mutable.ArrayBuffer.empty[Step] 

    private def context: Map[String, Any] = 
    globalBindings.foldLeft(Map[String, Any]())((l, r) => l + r) ++ Map[String, Any]("steps" -> steps.foldLeft(Vector[Map[String, Any]]())((l, r) => l.+:(r.bindings))) 
} 

但我認爲它可以簡化,從而不需要在「語境」法第一foldLeft 。

期望的結果是生成一個映射,其中的條目值是String,稍後將調用toString的對象或返回String的函數。

這是我可以用Scala的類型系統做的最好的,還是我可以讓代碼更清晰?

TIA

+3

最好遠離「任何」99%的時間 - 你不是在寫Java(已經):) –

+1

爲什麼值類型必須有所不同?他們都不都評價爲「字符串」嗎?它可以是一個函數,將_evaluates_賦值爲'String'。該函數應該能夠處理如何評估給定字符串值的邏輯。 –

回答

2

首先,上mutable.HashMaptoMap方法返回一個immutable.Map。如果您真的需要一個向量,您可以使用map而不是內部foldLefttoVector,這可能是不必要的。最後,您可以使用+將所需的「步驟」鍵值對添加到地圖。

所以你的整個方法體可能是:

globalBindings.toMap + ("steps" -> steps.map(_.bindings).toVector) 

我還注意到,你應該擔心使用類型,比如在斯卡拉Map[String, Any]的。 Scala的大部分功能都來自它的類型系統,並且可以在許多這樣的情況下使用它,所以這些類型通常被認爲是單一的。當然,在某些情況下,這種方法最有意義,如果沒有更多的上下文,很難確定這是否屬實。

+0

太棒了,謝謝。我知道Any是一種氣味,只是不確定如何糾正它。 val聲明怎麼樣,例如globalBindings,它們是否可以被寫入,否則它們必須具有Any類型,因爲它們可以是String,toStringable或(=> String)函數? – SilentICE

+1

您可以製作一個包含所有這些類型的包裝特徵,然後將其用作地圖的值類型。 –

+0

這聽起來不錯,但推動了我的Scala-foo的限制,你能給我更多的指針嗎?你的意思是像https://workday.github.io/scala/2015/02/05/scala-typesafe-wrappers/ – SilentICE