I defined the active pattern "Expression" as follows:
let (|Expression|_|) expression _ = Some(expression)
Now I'm trying to use it in this way:
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
But this results in "error FS0010: Unexpected symbol '-' in pattern". Is that fixable?
What am I trying to do is to write clearly a solution to the following equation:
max(wl - cw * .25, 0) + max(wr - cw * .25) + cw * columnCount = ActualWid开发者_如何学Pythonth
where cw is the only variable.
Can you suggest any better way?
The langauge of expressions that can be used as arguments for parameterized active patterns is limited in some ways. As far as I can tell, the F# specification doesn't say that explicitly, but the grammar suggests that it must be possible to parse the argument expression as pat-param
(page 90):
pat-param :=
| const
| long-ident
| [ pat-param ; ... ; pat-param ]
| ( pat-param, ..., pat-param )
| long-ident pat-param
| pat-param : type
| <@ expr @>
| <@@ expr @@>
| null
So, I think you'll need to write your pattern matching differently. You could turn the expressions into ordinary arguments of the match
construct and write something like this:
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
If the pattern used in the expression is always the same, you could also use active pattern like:
let (|Calculate|) w p _ =
(totalWidth - w) / (float model.Columns.Count - p)
... and then write something like:
let wDif = wLeft - wRight
match () with
| Calculate wDif 0.5 cw -> cw
| Calculate wLeft 0.25 cw -> cw
// .. etc.
精彩评论