开发者

How can I pass complex expression to parametrized active pattern?

开发者 https://www.devze.com 2023-03-08 21:59 出处:网络
I defined the active pattern \"Expression\" as follows: let (|Expression|_|) expression _ = Some(expression)

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.
0

精彩评论

暂无评论...
验证码 换一张
取 消