F#多条件if / else与匹配 [英] F# multi-condition if/else versus matching

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

问题描述

我是F#的新手,并且一直在实施简单的算法来学习语言结构。我使用 if / else 实现了对分方法,然后想要学习如何使用匹配来完成。



<$ p $如果fc = 0.0,那么printfn%i /%i - f(%f)=%f,f(%f)=%f,f(%f)=%fnew_count na如果((b-a)* 0.5),则b bb bc fc
else else eps然后printfn%i /%i - f(%f)=%f,f(%f)=%f,f(%f)=%fnew_count na fa b fb c fc
else if new_count = n then printfn%i /%i - f(%f)=%f,f(%f)=%f,f(%f)=%fnew_count na fa b fb c fc
否则,如果fc * fa< 0.0然后平分c new_count
else if fc * fb< 0.0然后bisect cb new_count

我发现使用匹配a,b,fa ,fb,fc 会导致类型错误,如果我只接受一个参数,我可以忽略参数并检查我的条件。什么是惯用的F#/功能方式来使用匹配呢?还是应该坚持if / else?

 匹配a和
| a when fc = 0.0 - > (%f)=%f,f(%f)=%fnew_count n a fa b fb c fc
| a((b-a)* 0.5) eps - > (%f)=%f,f(%f)=%fnew_count n a fa b fb c fc
| a when new_count = n - > (%f)=%f,f(%f)=%fnew_count n a fa b fb c fc
| a when fc * fa< 0.0 - > bisect c new_count
| a when fc * fb< 0.0 - > bisect cb new_count


解决方案

您的条件都处理不同的事情,彼此无关,所以如果 s的字符串就好了。我推荐的唯一方法是使用 elif 而不是 else if



match 应该被理解为给出这个可以具有不同风味的东西,这里是如何处理这些风味的。 match 的一个特别的优势是编译器会找出并告诉你,如果你错过了任何风味。特别是,你在你的问题中给出的代码应该产生一个编译器警告,抱怨不完整的模式匹配这个表达式。考虑一下:当所有情况都不匹配时,表达的结果是什么?



如果 if s ,这也将是这种情况。例如,这不会编译:

  let x = if a< 5然后7 

为什么?因为编译器知道 a< 5 (即它应该是 7 ),但它应该是什么?编译器不能为你做出决定,所以它会产生一个错误。

另一方面,它会编译:

  let x = if a< 5 then 7 else 8 

但在您的特殊情况下,编译器可以让您摆脱这种情况,因为因为 printf 返回单位所有分支都会返回一个单位 c>,其他都是递归的)。换句话说,下面将编译:

  let x = if a a< 5然后()

以下内容:

  let x = if a< 5然后printf嘘! 

编译器让你避开这个,因为 unit 是特殊的:它只能有一个值(即()),所以编译器可以为你决定结果当条件不是 true



这个表达式的一个实际结果是,如果你没有仔细考虑你的条件,可以想象会发生这样的情况,以至于你的条件都不是 true ,所以整个事情将返回 unit 并且不打印任何东西。我不能说这是否会在您的特定情况下发生,因为我没有看到整个函数定义。


I'm new to F# and have been implementing simple algorithms to learn the language constructs. I implemented the bisection method using if/else and then wanted to learn how to do it using matching.

if fc = 0.0                   then printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
else if ((b - a) * 0.5) < eps then printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
else if new_count = n         then printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
else if fc * fa < 0.0         then bisect a c new_count
else if fc * fb < 0.0         then bisect c b new_count 

I found that using match a, b, fa, fb, fc would cause type errors, where if I took just a single parameter I could essentially ignore the parameter and check my conditions. What is the idiomatic F#/Functional way to use matching for this? Or should I just stick to if/else?

 match a with 
    | a when fc = 0.0              ->  printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
    | a when ((b - a) * 0.5) < eps -> printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
    | a when new_count = n         -> printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
    | a when fc * fa < 0.0         -> bisect a c new_count
    | a when fc * fb < 0.0         -> bisect c b new_count 

解决方案

Your conditions all deal with disparate things, unrelated to each other, so the string of ifs is just fine. The only thing I'd recommend is using elif instead of else if.

match should be understood along the lines of "given this thing that can be of different flavors, here's how to handle those flavors". One particular strength of match is that the compiler will figure out, and tell you, if you missed any of the "flavors". In particular, the code you gave in your question should produce a compiler warning, complaining that "Incomplete pattern matches on this expression". Think about it: what would be the result of that expression when none of the cases match?

With ifs, this will also be the case. For example, this doesn't compile:

let x = if a < 5 then 7

Why? Because the compiler knows what the result should be when a < 5 (i.e. it should be 7), but what should it be otherwise? The compiler can't decide for you, so it will generate an error.
This, on the other hand, would compile:

let x = if a < 5 then 7 else 8

But in your particular case, the compiler lets you get away with this, because all your branches return a unit (why? because printf returns unit, and all others are recursive). In other words, the following will compile:

let x = if a < 5 then ()

And the following:

let x = if a < 5 then printf "boo!"

The compiler lets you get away with this, because unit is special: it can only ever have one value (namely, ()), so the compiler can decide for you what the result of the expression would be when the condition isn't true.

One practical upshot of this would be that, if you didn't think about your conditions very carefuly, it could conceivably happen so that none of your conditions are true, and so the whole thing will return unit and not print anything. I can't say if that could happen in your particular case, because I don't see the whole function definition.

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

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