2017-01-11 73 views
5

我正在使用Javaslang-2.1.0-alpha及其Javaslang-match等價物來做一些對象分解。據this by blog後由丹尼爾的「匹配花式的方式」一節中:Javaslang對象分解不起作用

Match(person).of(Case(Person("Carl", Address($(), $())), (street, number) -> ...)) 

如果檢索匹配內部Address兩個通配符模式值到streetnumber不過的例子甚至不編譯。後來我意識到所有對象都必須被包裝在原子模式中,即「Carl」變成$(「Carl」)。這是在閱讀this issue後。

我跟着updated tutorial但這個例子沒有更新。

我的例子更新到這一點:

Person person = new Person("Carl", new Address("Milkyway", 42)); 

String result2 = Match(person).of(
Case(Person($("Carl"), Address($(),$())), 
     (street, number) -> "Carl lives in " + street + " " + number), 
Case($(),() -> "not found") 
); 
System.out.println(result2); 

它編譯,但我的價值沒有被正確匹配,從控制檯輸出判斷:

Carl lives in Carl Address [street=Milkyway, number=42] 

很明顯,street包含卡爾number,整個Address對象。

當我嘗試添加第三拉姆達參數趕上卡爾

Case(Person($("Carl"), Address($(),$())), 
     (name, street, number) -> "Carl lives in " + street + " " + number) 

的代碼無法編譯,lambda表達式得到一個紅色下劃線與下面的錯誤文本:

The target type of this expression must be a functional interface 

在最新版本的javaslang-match中,沒有辦法忽略$_的值。所以我想匹配每個原子模式,它將返回如上所述的三個lambda參數。

我需要理解這個庫的人來向我解釋如何在最新版本中做這個對象分解。

回答

7

聲明:我是Javaslang的創造者。

該情況需要處理(String,Address) - > {...}。 $()匹配任意值,但處理程序/函數僅接收分解對象樹的第一層。 $()在第二層。

規則:所有圖層都與模式匹配,只有第一層被傳遞給處理程序。

Match的第一個原型實際上處理任意樹深度,但是在所有可能的組合下都會生成方法帽 - 最大字節代碼容易被超出,編譯時間以指數方式分解爲無限大。

Match的當前版本是我目前看到的Java中唯一實用的方法。

更新:

請讓我放棄對這個話題更加形象化的更新。

我們

  1. 區分輸入的對象圖
  2. 傳遞給匹配情況
  3. 分解對象的對象圖的模式樹

廣告1)對象圖

給定一個對象,通過遍歷屬性(resp。該對象的實例變量)。值得注意的是,我們並不禁止一個對象包含循環(例如包含自身的可變列表)。

在Javaslang中沒有天然如何將對象分解爲其部分。爲此,我們需要一個所謂的模式。一個對象圖的

實施例:

 Person  <-- root 
    / \ 
"Carl" Address <-- 1st level 
     / \ 
"Milkyway" 42 <-- 2nd level 

廣告2)模式樹

的圖案(實例)固有地定義如何分解一個對象。

在我們的例子中,模式類型如下所示(簡化仿製藥):

Pattern2<Person, String, Address<String, Integer>> 
      /   \ 
Pattern0<String> Pattern2<Address, String, Integer> 
         / \ 
      Pattern0<String>  Pattern0<Integer> 

被叫模式方法返回上述類型的實例:

 Person(...) 
     / \ 
$("Carl") Address(...) 
      / \ 
      $() $() 

Javaslang比賽API執行以下操作:

  1. Match實例將給定的person對象傳遞給fi第一種情況。
  2. 爲例傳遞person對象到圖案Person(...)
  3. Person(...)圖案檢查如果給定對象personPerson類型。
    • 如果爲真,則圖案分解對象到其零件 (由元組代表),並檢查是否在子圖案$("Carl")Address(...)匹配這些部件(遞歸地重複3)
    • 如果爲假,則匹配將對象傳遞給下一個Case(請參閱2.)
    • 如果模式是原子模式,即它不能再分解對象,則檢查相等性,並將調用者一直通知給匹配大小寫。
  4. 當匹配的情況下得到了一個模式匹配然後將其傳遞對象圖到匹配的情況下的處理程序的第一級的分解對象。

目前Java的類型系統不允許我們通過在類型化的方式來處理程序的任意對象圖/樹平匹配的對象。

廣告3)分解的對象

我們已經在2提到的目的以上分解)。特別是當我們的給定對象的部分被髮送到模式樹中時,它被使用。

因爲我們上面提到的類型的系統的限制,我們分離的匹配處理分解部件的處理的對象的處理。

Java允許我們匹配任意對象圖。我們不限於此處的任何級別。

但是,當一個對象成功匹配時,我們只能將第一層的分解對象傳遞給處理程序。

在我們的示例中,這些分解對象是name和給定person(而不是streetnumber)的address


我知道這對Match API的用戶來說並不明顯。

其中一個Java版本將包含值對象和本機模式匹配!但是,該版本的模式匹配將完全限於第一級。

Javaslang允許匹配任意對象圖 - 但它有一個價格。處理程序只接收第一層分解對象,這可能會造成混淆。

我希望這能以一種可以理解的方式回答問題。

- 丹尼爾

+0

讓我再重複一下我現在明白了:事情的方式,目前,如果我們要實現什麼,我想實現,我們必須手工分解內部人地址對象,並把所有地址屬性直接在Person下。它是否正確?? – egima

+0

@egima是的,這是正確的! (對於遲到的答案感到抱歉 - 不知何故,我沒有通知) –