2017-06-09 20 views
0

使用Monocle我可以定義一個鏡頭看沒有問題的情況下,類成員,如何打印單片眼鏡鏡片的屬性訪問器風格的字符串

val md5Lens = GenLens[Message](_.md5) 

這可以用來比較的md5兩個物體之間的值並且在值不同時失敗並顯示包含字段名稱的錯誤消息。

有沒有一種方法可以從Lens中單獨生成一個用戶友好的字符串,用於識別鏡頭讀取的字段?我想避免明確提供字段名稱

val md5LensAndName = (GenLens[Message](_.md5), "md5") 

如果有一種解決方案也適用於具有多個組件的鏡頭,則效果會更好。對我來說,即使解決方案只能工作到一個深度,情況也不錯。

回答

1

這是根本不可能的。從概念上講,鏡頭只不過是一對功能:一個是從對象獲取一個值,另一個是使用給定值獲取新對象。該功能可以通過訪問源對象字段的方式來實現。實際上,即使是GenLens宏也可以使用像​​3210這樣的鏈式場訪問器來爲嵌套對象的字段生成複合透鏡。起初可能會讓人困惑,但這個功能有其用處。例如,您可以斷開數據存儲和代表性的格式:

import monocle._ 

case class Person private(value: String) { 

    import Person._ 

    private def replace(
    array: Array[String], index: Int, item: String 
): Array[String] = { 
    val copy = Array.ofDim[String](array.length) 
    array.copyToArray(copy) 
    copy(index) = item 
    copy 
    } 

    def replaceItem(index: Int, item: String): Person = { 
    val array = value.split(delimiter) 
    val newArray = replace(array, index, item) 
    val newValue = newArray.mkString(delimiter) 
    Person(newValue) 
    } 

    def getItem(index: Int): String = { 
    val array = value.split(delimiter) 
    array(index) 
    } 
} 

object Person { 

    private val delimiter: String = ";" 

    val nameIndex: Int = 0 

    val cityIndex: Int = 1 

    def apply(name: String, address: String): Person = 
    Person(Array(name, address).mkString(delimiter)) 
} 

val name: Lens[Person, String] = 
    Lens[Person, String](
    _.getItem(Person.nameIndex) 
)(
    name => person => person.replaceItem(Person.nameIndex, name) 
) 

val city: Lens[Person, String] = 
    Lens[Person, String](
    _.getItem(Person.cityIndex) 
)(
    city => person => person.replaceItem(Person.cityIndex, city) 
) 

val person = Person("John", "London") 
val personAfterMove = city.set("New York")(person) 
println(name.get(personAfterMove)) // John 
println(city.get(personAfterMove)) // New York 

雖然不是很高性能的,這個例子說明了想法:Person類沒有cityaddress領域,但通過包裝數據提取和我們可以假裝它有它們。對於更復雜的物體,透鏡組成如常工作:內部透鏡僅對提取物體進行操作,依靠外部透鏡將其折回。

+2

即使您有一個字段鏈需要處理,對於類似LabellessGeneric的字段來標記'HList'字段,在字段中使用標籤的概念並不是概念上不可能的。如果不修改Lens的隱式宏,或者按照'LabelledGeneric'的精神實現'LabelledLens',就不可能實現。 – flavian

+0

我可以通過使用基於屬性訪問器的DSL的https://github.com/kenbot/goggles來解決我的問題。 –