我将事件模式“Expression”定义如下:
let (|Expression|_|) expression _ = Some(expression)
现在我尝试以这种方式使用它:
match () with
| Expression((totalWidth - wLeft - wRight) / (float model.Columns.Count - 0.5)) cw
when cw <= wLeft * 4. && cw <= wRight * 4. ->
cw
| Expression((totalWidth - wLeft) / (float model.Columns.Count - .25)) cw
when cw <= wLeft * 4. && cw > wRight * 4. ->
cw
| Expression((totalWidth - wRight) / (float model.Columns.Count - .25)) cw
when cw > wLeft * 4. && cw <= wRight * 4. ->
cw
| Expression(totalWidth / float model.Columns.Count) cw
when cw > wLeft * 4. && cw > wRight * 4. ->
cw
| _ -> System.InvalidProgramException() |> raise
但这会导致“错误 FS0010:模式中出现意外符号‘-’”。这是可以修复的吗?
我想做的是清楚地写出以下方程的解:
max(wl - cw * .25, 0) + max(wr - cw * .25) + cw * columnCount = ActualWidth
其中 cw 是唯一的变量。
你能推荐更好的方法吗?
最佳答案
可用作参数化事件模式参数的表达式语言在某些方面受到限制。据我所知,F# specification没有明确说明,但语法表明必须可以将 参数表达式 解析为 pat-param
(第 90 页):
pat-param :=
| const
| long-ident
| [ pat-param ; ... ; pat-param ]
| ( pat-param, ..., pat-param )
| long-ident pat-param
| pat-param : type
| <@ expr @>
| <@@ expr @@>
| null
因此,我认为您需要以不同的方式编写模式匹配。您可以将表达式转换为 match
构造的普通参数并编写如下内容:
match
(totalWidth - wLeft - wRight) / (float model.Columns.Count - 0.5),
(totalWidth - wLeft) / (float model.Columns.Count - .25),
(totalWidth - wRight) / (float model.Columns.Count - .25)
with
| cw1, _, _ when cw1 <= wLeft * 4. && cw1 <= wRight * 4. -> cw1
| _, cw2, _ when cw2 <= wLeft * 4. && cw2 > wRight * 4. -> cw2
| _, _, cw3 when cw3 > wLeft * 4. && cw3 <= wRight * 4. -> cw3
| _ -> totalWidth / float model.Columns.Count
如果表达式中使用的模式始终相同,您还可以使用事件模式,如:
let (|Calculate|) w p _ =
(totalWidth - w) / (float model.Columns.Count - p)
...然后写这样的东西:
let wDif = wLeft - wRight
match () with
| Calculate wDif 0.5 cw -> cw
| Calculate wLeft 0.25 cw -> cw
// .. etc.
关于f# - 如何将复杂的表达式传递给参数化的事件模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6168851/