2015-07-20 58 views
1

try method是核心Ruby的常見擴展。例如,它在Rails中默認可用。 try只有當它不是nil(Ruby的null)時,纔會在對象上執行一個方法或一段代碼。它的用法有三種形式:Scala等效於Ruby中的ActiveSupport的Object.try

  1. 調用非nil對象的方法,並返回結果:
    customer_or_nil.try(:save)

  2. 鏈接的代碼的任意塊中的表達式如果結果到目前爲止不nil
    obj.try { |non_nil_obj| do_something(non_nil_obj) }

  3. (2)使用不用於可選的處理,但作爲一種方法來繼續鏈狀表達式,其中在步驟n + 1個的方法要求必須根據步驟n的結果而計算出的參數的擴展:
    data.analyze.try { |result| result.compress(optimal_settings(result)) }.save

我在Scala的當量(3)或可替換的Scala成語的,將允許特別感興趣,例如,與此相關的代碼的Apache火花的DataFrame

val df = ctx.sql("select * from my_table") 
df. 
    repartition(max(1, df.rdd.partitions.size/4)). 
    saveAsTable("repartitioned_table") 

被重構到類似如下(使用Ruby語法)

ctx. 
    sql("select * from my_table"). 
    try { |df| df.repartition(max(1, df.rdd.partitions.size/4)) }. 
    saveAsTable("repartitioned_table") 

重構的目標是通過維持一個單一的方法鏈以提高可讀性和通過保持df限定範圍在步驟減少範圍污染它絕對需要的鏈條。

注:我特別不感興趣的優點和使用Option可選處理的利弊討論,因爲這不是try這個問題涉及的主要用例。

+0

一種-理解應該做的工作。 Scala中的'Try'是一個monad,意味着'flatmap()'被定義在它上面。 ''flatmap()'在'Try'上工作的方式是將其參數應用於成功的路徑。 '爲{df < - ctx.sql(...); rep < - repartiion(...); sat < - saveAsTable(...); }' –

+0

@BobDalgleish你錯過了這個問題的目的:我正在尋找一個支持方法鏈接的答案。看看Alexey的回答。 – Sim

回答

1

不是在標準庫,而是一個相當於3個很容易寫(try是一個關鍵字,所以改名爲ap(簡稱apply)):

implicit class TryOp[A](x: A) { 
    def ap[B](f: A => B): B = f(x) 
} 

ctx. 
    sql("select * from my_table"). 
    ap { df => df.repartition(max(1, df.rdd.partitions.size/4)) }. 
    saveAsTable("repartitioned_table") 
+1

不適用於我:'null.ap(identity _)// :12:error:value ap is not the member of Null' –

+0

@JörgWMittag我可以重現上面的錯誤,但是當我使用'ap '什麼應該是來自Spark SQL的null值(使用'Any'值變量)我沒有錯誤。 – Sim

+0

Alexey,以任何方式解決@JörgWMittag發現的問題? – Sim