模式匹配与守卫vs在F#中的if/else构造

pad*_*pad 8 f# functional-programming pattern-matching guard-clause

在ML系列语言中,人们倾向于选择模式匹配来if/else构建.在F#中,在模式匹配中使用防护装置if/else在很多情况下很容易替换.

例如,delete1可以在不使用if/else(参见delete2)的情况下重写一个简单的函数:

let rec delete1 (a, xs) =
    match xs with
    | [] -> []
    | x::xs' -> if x = a then xs' else x::delete1(a, xs') 

let rec delete2 (a, xs) =
    match xs with
    | [] -> []
    | x::xs' when x = a -> xs'
    | x::xs' -> x::delete2(a, xs') 
Run Code Online (Sandbox Code Playgroud)

另一个例子是求解二次函数:

type Solution =
    | NoRoot
    | OneRoot of float
    | TwoRoots of float * float

let solve1 (a,b,c) = 
    let delta = b*b-4.0*a*c
    if delta < 0.0 || a = 0.0 then NoRoot 
    elif delta = 0.0 then OneRoot (-b/(2.0*a))
    else 
        TwoRoots ((-b + sqrt(delta))/(2.0*a), (-b - sqrt(delta))/(2.0*a))

let solve2 (a,b,c) = 
    match a, b*b-4.0*a*c with
    | 0.0, _  -> NoRoot
    | _, delta when delta < 0.0 -> NoRoot
    | _, 0.0 -> OneRoot (-b/(2.0*a))
    | _, delta -> TwoRoots((-b + sqrt(delta))/(2.0*a),(-b - sqrt(delta))/(2.0*a))
Run Code Online (Sandbox Code Playgroud)

我们应该使用与守卫的模式匹配来忽略丑陋的if/else构造吗?

使用与警卫的模式匹配是否有任何性能影响?我的印象是它似乎很慢,因为在运行时检查了模式匹配.

Ank*_*kur 9

两者都有自己的位置.人们更习惯使用If/else构造来检查一个值,其中模式匹配就像类固醇上的If/else一样.模式匹配允许您对decomposed数据结构进行排序,并使用gaurds指定分解数据部分或其他值的某些附加条件(特别是在递归数据结构或F#中所谓的区分联合的情况下) .

我个人更喜欢使用if/else进行简单的值比较(true/false,int等),但是如果你有一个递归数据结构或需要与其分解值进行比较的东西,那么没有比模式匹配更好的了.

首先使它工作并使其优雅和简单然后如果你看起来有一些性能问题然后检查性能问题(这主要是由于一些其他逻辑而不是由于模式匹配)

  • +1'为'分解'部分.实际上,区分模式匹配和if/else构造是一个很好的观点. (4认同)

Dan*_*iel 7

正确的答案可能取决于,但我猜测,在大多数情况下,编译的表示是相同的.举个例子

let f b =
  match b with
  | true -> 1
  | false -> 0
Run Code Online (Sandbox Code Playgroud)

let f b =
  if b then 1
  else 0
Run Code Online (Sandbox Code Playgroud)

两者都转化为

public static int f(bool b)
{
    if (!b)
    {
        return 0;
    }
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

鉴于此,它主要是风格问题.我个人更喜欢模式匹配,因为案例总是对齐的,使其更具可读性.此外,他们(可以说)更容易扩展,以处理更多案件.我认为模式匹配是if/ then/ 的演变else.

模式匹配也没有额外的运行时成本,有或没有防护.

  • 实际上,根据我的经验,复杂的模式匹配比复杂的if/then/else语句编译成更高效的代码,因为编译器可以代表您删除冗余的条件评估. (2认同)