可以在一行中优化模式匹配代码段吗?

时间:2019-02-24 04:43:12

标签: f#

我想知道是否有一种方法可以在不使用两次将calcVol函数传递给h的情况下写此行?

| h :: t when (h |> calcVol) > maxVol -> maxLoop t (h |> calcVol) 

其中h是一个包含三个维度的元组,而calcVol返回一个浮点值。

我知道我可以将vol值明确定义为:

| h :: t -> let vol = calcVol h if vol > maxVol then...

我想知道是否有一种方法可以很好地做到这一点?

2 个答案:

答案 0 :(得分:1)

如果vol的所有用法都在箭头之前,则可以执行以下操作:

| h :: t when let vol = (h |> calcVol) in vol > maxVol -> // Something

但是箭头左侧let子句中的when分配不会移到右侧。演示:

let f x = x + 5
let l = [1; 2]
match l with
| a :: b when let y = f a in y = 6 -> "Six"
| _ -> "Other"

这有效,并返回"Six"。但是:

let f x = x + 5
let l = [1; 2]
match l with
| a :: b when let y = f a in y = 6 -> sprintf "Six = %d" y
| _ -> "Other"

这不起作用,产生错误:

  

错误FS0039:未定义值或构造函数'y'

很遗憾,您无法获得所需的单行版本,因此必须采用更长的方法(let后跟{{1 }},如您在答案的后半部分所演示的那样。

答案 1 :(得分:1)

使用活动模式,解决方案可能如下所示:

let calcVol v = v

let (|MaxVol|) maxVol = function
| [] -> (maxVol, [])
| h :: t -> ((max (calcVol h) maxVol), t)

let rec maxLoop list m =
    match list with
    | [] -> m
    | MaxVol m (c, t) -> maxLoop t c

let vs = [ -1; 42; 3 ]

maxLoop vs System.Int32.MinValue // 42

具有更好可读性的另一种可能性可能是首先计算体积(例如通过map ping),然后找到最大值。没有完整的代码很难说...