2016-08-02 68 views
2

我搞乱了F#和寓言,并试图测试我的理解。为此,我试着创建一个函数来计算给定的迭代次数。我想出来的是F#:不理解匹配..与

let eCalc n = 
     let rec internalECalc ifact sum count = 
      match count = n with 
      | true -> sum 
      | _ -> internalECalc (ifact/(float count)) (sum + ifact) (count+1) 

     internalECalc 1.0 0.0 1 

工作正常,返回2.7182818284590455当

eCalc 20 

称为但是,如果我尝试使用,我的想法是,更正确的形式

let eCalc n = 
     let rec internalECalc ifact sum count = 
      match count with 
      | n -> sum 
      | _ -> internalECalc (ifact/(float count)) (sum + ifact) (count+1) 

     internalECalc 1.0 0.0 1 

我得到一个警告“[警告]这个规则永远不会匹配(L5,10-L5,11)”,并且返回值为0.(并且如果我交换'n'和'count '在比赛声明中)。在比赛声明中我不能使用'n'是否有原因?有没有办法解决这个问题,所以我可以使用'n'?

感谢

回答

10

当您在match语句中使用的名称,你检查它在分配给该变量你觉得你的方式的价值。您改为指定该名称。即,

match someInt with 
| n -> printfn "%d" n 

将打印值为someInt。这相当于let n = someInt; printfn "%d" n

你想要做的是使用when条款;在when子句中,您不是模式匹配的,但是在检查时执行“标准”。所以你想要的是:

let eCalc n = 
     let rec internalECalc ifact sum count = 
      match count with 
      | cnt when cnt = n -> sum 
      | _ -> internalECalc (ifact/(float count)) (sum + ifact) (count+1) 

     internalECalc 1.0 0.0 1 

这是有道理的,还是你需要我进入更多的细节?

P.S.在像这样的情况下,您的匹配函数看起来像“x when(布尔条件涉及x) - > case 1 | _ - > case 2”时,使用简单的if表达式可读性更高一些:

let eCalc n = 
     let rec internalECalc ifact sum count = 
      if count = n then 
       sum 
      else 
       internalECalc (ifact/(float count)) (sum + ifact) (count+1) 

     internalECalc 1.0 0.0 1 
+4

这是一个很好的解释,所以upvote :)我认为,一个更简单,更习惯的解决方案,但是,将使用“if/then/else”表达式。 –

+0

是的,在这种情况下,“if/then/else”更好。我希望尽可能接近OP的原始代码来说明差异,但我不妨编辑答案以显示更好的方式。 – rmunn

+0

我认为这样可以显示模式匹配语法,因此我会将它留在答案中,但也可能会添加* if/then/else'选项。 –