2016-09-28 44 views
1

我正在erlang編寫一個函數,它應該能夠接受不同順序和不同格式的各種參數集,我使用非常嚴格的警衛來確保正確的匹配。在長衛士中刪除orelse和andalso

的情況並不少見,我寫了一個很長衛是這樣的:在這裏

my_fun(List, Number, OptionalList, Record) 
when is_list(List) andalso length(List) >= 5, 
    is_integer(Number) andalso Number >= 10 andalso Number =< 50 orelse Number =:= undefined, 
    is_list(OptionalList) orelse OptionalList =:= undefined, 
    is_record(Record, my_record) -> 

我使用否則別指望和andalso了很多,這讓代碼少了很多可讀的,只是一般較長。

有沒有一種方法來實現相同的保護邏輯使用,並;只要?

+1

考慮使用宏?例如,當「is_integer_in_range(數字,10,50)」時。 –

回答

6

不,你需要保留一些orelseandalso,自使用,;時,你實際上有多個解決方案(由;分隔)組成的幾個條件(通過,分隔),並至少在其中一個選項中的每個條件都必須爲真。在這個例子中,你有幾乎相反的情況:對於每個參數,你想要條件中的一個爲真。

換句話說,這樣的後衛:

A, B; C, D 

(幾乎)等同於:

(A andalso B) orelse (C andalso D) 

,也沒有辦法做到像(A orelse B) andalso (C orelse D)沒有使用這些運營商。

可以使這個例子有點短,但:

  • is_list(List)是多餘的,因爲如果length(List)List不是列表將失敗。在後衛中,「失敗」並不意味着拋出錯誤;這僅表示該子句不匹配。
  • is_integer(Number)差不多多餘的,因爲你也有Number >= 10 andalso Number =< 50。在Erlang中,任何兩個術語都可以比較大小,所以如果Number在這個範圍內,那肯定是一個數字。 (這可能是一個浮點數,而不是一個整數,雖然)代替is_record(Record, my_record)
  • ,你可以匹配在函數頭記錄:

    my_fun(List, Number, OptionalList, Record = #my_record{}) 
    

如果AB會拋出異常,orelse版本將不匹配,而;版本將匹配,如果C, D部分匹配。例如,此函數返回b

foo() when 1/0 == 1 orelse true -> 
    a; 
foo() when 1/0 == 1; true -> 
    b.