2010-08-26 37 views
3

在Java或C++編程時,有很多次我已經遇到了一個簡單的模式,其中自定義控件結構可以減少我的代碼中的樣板文件。它類似於:斯卡拉的自定義控制結構?

if(Predicate){ 
    Action 

    return Value 
} 

即,「返回if」類型語句。我嘗試過使用像foo[A,B](pred:((A,A)=>Boolean), value:Option[B])這樣的簽名來做功能,但後來我檢查了是否返回了Some或None。我被return聲明絆倒了。

在功能語言或更具體的Scala中是否有繼承方式製作這樣的控制結構?

編輯:

我是不是跟我描述清晰,它是誰試圖幫助我的人混淆。我的foo不起作用的關鍵原因是它不能短路包含函數的評估。那就是

def intersect(geometry:Geometry, reference:Geometry):Geometry = { 
    return_if(withinBounds(geometry, projection), logToString(logger, "Geometry outside " + projection.toString), EmptyGeometry()) 
    return_if(topologicallyCorrect(geometry), intersect(correct(geometry), reference) 
    //rest of the function 
} 

仍然允許在return_if內的尾部遞歸。

+0

它*可能*有可能以某種方式獲得這種行爲(CPS是「內置」爲2.8,但必須由編譯器開關激活),但我對此不夠了解。 – Landei 2010-08-26 20:49:45

回答

2

嗯,據我瞭解,你想在控制結構中的回報,退出它被嵌入的功能。

所以,在你的榜樣應該退出方法相交?

我不確定這是否可能。因爲Return_if內部的返回將始終退出return_if,我不認爲有辦法告訴scala,返回應該退出嵌入的return_if函數。

我希望我能理解你想要做什麼: )

+0

是的,你是對的。我甚至沒有想到這一點。如果return_if傳遞了return_if,它可能會導致問題。 – wheaties 2010-08-26 19:59:41

+3

實現此目的的方法是拋出一個異常,然後通過外部方法處理異常 - 查看「break」是如何實現的。而不是'return',你會調用一個會拋出異常的方法(比如'break') – 2010-08-26 21:15:41

2

它看起來像你使用這個作爲條件轉義從代碼的控制流。

你也可以在Scala中做到這一點(只是註釋方法返回的類型),如果它真的是最優雅的解決方案。有時代碼需要像多級過濾器一樣行事,這種模式對此很有效。

當然,你總是可以嵌套if語句,但會變得尷尬。

但是,在Scala中還有其他幾件事情需要考慮。人們可以

methodReturningOption.getOrElse(
    // All the code for the None case goes in here 
) 

通常工作得很好,在有一個合理的默認的情況下整合不同部門(或你最終會拋出一個異常,如果有沒有)。

或者,您也可以濫用模式匹配此:

None match { // Could use a real variable instead of None if it helped 
    case _ if (Predicate1) => Action1; Value1 
    case _ if (Predicate2) => Action2; Value2 
    . . . 
    case _ => ErrorHandlingPerhaps 
} 

但是,你也許還能想想您的問題以不同的方式,使這些類型的謂詞變得不太有用。 (不知道更多的細節,我不能建議什麼的。)

7

我會用部分功能:

def whatevs[A, B](options : PartialFunction[(A,A), B]) : Option[B] = { 
    val myInput = generateInput 
    if(options.isDefined(myInput)) { 
    Some(options(myInput)) 
    } else None 
} 

然後您的使用情況可能如下所示:

whateves { 
    case (x,y) if x > y => "Biggerz" 
    case (x,y) if y > x => "Tiny!" 
} 

一般,你不需要返回語句。如果-expression將評估爲每個塊中使用的最後一個表達式。您可能需要幫助編譯器找出if表達式的類型結果,但返回值不需要。

部分函數是一種機制,如果某些條件成立,則執行操作。在上面,這兩個條件是來自元組的x> y或y> x。

如果whatevs函數不是你所說的,我建議使用原始模式匹配。

1

我不知道爲什麼要這樣做。這裏是你想要編寫代碼:

def intersect(geometry:Geometry, reference:Geometry):Geometry = { 

    return_if(withinBounds(geometry, projection), 
    logToString(logger, "Geometry outside " + projection.toString), 
    EmptyGeometry()) 

    return_if(topologicallyCorrect(geometry), 
    intersect(correct(geometry)), 
    reference) 

    // rest of the function 
} 

,而這裏就是它看起來像在「普通」的斯卡拉:

def intersect(geometry:Geometry, reference:Geometry):Geometry = { 

    if (withinBounds(geometry, projection)) { 
    logToString(logger, "Geometry outside " + projection.toString) 
    return EmptyGeometry() } 

    if(topologicallyCorrect(geometry)) { 
    intersect(correct(geometry)) 
    return reference } 

    //rest of the function 
} 

對我來說,「普通」版本看起來更加清晰。一方面,它清楚地說明返回的內容。它並不更詳細。我懷疑你有更復雜的用例。如果你告訴我們,也許我們將能夠引導你更合適的模式。