2016-09-28 43 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.