与守卫模式匹配与if / else构建F# [英] Pattern matching with guards vs if/else construct in F#

查看:140
本文介绍了与守卫模式匹配与if / else构建F#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ML族语言中,人们倾向于将模式匹配优先于 if / else 构造。在F#中,在许多情况下,在模式匹配中使用警卫很容易替换 if / else 。例如,一个简单的 delete1 函数可以重写而不使用 if / else (见 delete2 ):

  let rec delete1(a,xs)= 

|匹配xs [] - > []
| x :: xs' - >如果x = a,则xs'else x :: delete1(a,xs')

let rec delete2(a,xs)=
匹配xs with
| [] - > []
| x :: xs'when x = a - > xs'
| x :: xs' - > x :: delete2(a,xs')

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

  type Solution = 
| NoRoot
| OneRoot of float
| float的两个根* float

让solve1(a,b,c)=
让delta = b * b-4.0 * a * c
如果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))

让solve2(a,b,c)=
匹配a,b * b-4.0 * a * c与
| 0.0,_ - > NoRoot
| _,当delta < 0.0 - > NoRoot
| _,0.0 - > OneRoot(-b /(2.0 * a))
| _,delta - >两根(( - b + sqrt(delta))/(2.0 * a),( - b - sqrt(delta))/(2.0 * a))

如果我们使用模式匹配和守卫来忽略丑陋 if / else 构造?

使用模式匹配与守卫有任何性能暗示吗?我的印象是它似乎很慢,因为在运行时检查了模式匹配。

解决方案

正确的答案可能是它取决于,但我推测在大多数情况下,编译代表性是一样的。举个例子

  let f b = 
匹配b和
|真 - > 1
|错误 - > 0

  let fb = 
if b then 1
else 0

都翻译成

  public static int f(bool b)
{
if(!b)
{
return 0;
}
返回1;
}

鉴于此,它主要是风格问题。就我个人而言,我更喜欢模式匹配,因为案例总是对齐,使得它更具可读性。此外,他们(可以说)更容易扩大后处理更多的案件。如果 / 然后 / else ,我认为模式匹配是 >。

模式匹配没有额外的运行时间成本,有或没有警卫。


In ML-family languages, people tend to prefer pattern matching to if/else construct. In F#, using guards within pattern matching could easily replace if/else in many cases.

For example, a simple delete1 function could be rewritten without using if/else (see 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') 

Another example is solving quadratic functions:

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))

Should we use pattern matching with guards to ignore ugly if/else construct?

Is there any performance implication against using pattern matching with guards? My impression is that it seems to be slow because pattern matching has be checked at runtime.

解决方案

The right answer is probably it depends, but I surmise, in most cases, the compiled representation is the same. As an example

let f b =
  match b with
  | true -> 1
  | false -> 0

and

let f b =
  if b then 1
  else 0

both translate to

public static int f(bool b)
{
    if (!b)
    {
        return 0;
    }
    return 1;
}

Given that, it's mostly a matter of style. Personally I prefer pattern matching because the cases are always aligned, making it more readable. Also, they're (arguably) easier to expand later to handle more cases. I consider pattern matching an evolution of if/then/else.

There is also no additional run-time cost for pattern matching, with or without guards.

这篇关于与守卫模式匹配与if / else构建F#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆