Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
Support C#-style Deconstruct method based pattern matching #751
The C#-way of doing quick pattern matching and value extraction is by declaring member functions of name
... which actively extracts values from the class instance.
In F#, we automatically receive pattern matching benefits for DUs and records, but currently the only way to peek into the content of a class instance in a pattern, is to create an active pattern for it. Since active patterns cannot be overloaded, one has to come up with different names for different ways of extraction, which adds extra complexity to the matter.
So I propose that we support this in F#.
Note, it's not
A quick glance of what it may look like:
type MyEventArgs() = inherits EventArgs() member val foo: int = 123 with get, set member x.Deconstruct([<Out>] foo: _ byref) = foo <- x.foo // later: myControl.MyEvent.Subscribe(fun (foo: int) -> printfn "extracted foo = %d" foo ) |> ignore
Pros and Cons
The advantages of making this adjustment to F# are:
The disadvantages of making this adjustment to F# are:
Estimated cost (XS, S, M, L, XL, XXL): M
Related suggestions: (put links to related suggestions here)
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply:
Ooh, good question!
Edit: escalating the workload estimation to 'M'.
An alternative may be to have a special pattern matching construct, e.g.
match x with | Deconstruct(a,b) -> ...
that is known to the compiler and looks for the
Combining this with a type test may also be important, a possible syntax is this:
match x with | :? Node1 as (Deconstruct(a,b)) -> ... // a full nested pattern would be allowed
I do understand why some F# programmers have down-voted this. Fully implicit, type directed deconstruction is really weird for F#, especially given the existence of active patterns in the language and the general lack of type-directed magic rules in pattern matching (a part of the language that is, I think, particularly prone to problems in code comprehension if magic is being applied).
@7sharp9 it turns out that many deconstruct members are implemented as extension members + out parameters, which is problematic from an 'active pattern with SRTP' perspective for a few reasons:
I think @baronfel has already covered the points, but let me try to rephrase:
First, the deconstruction methods are not necessarily attached to the types, so type constraints are not enough to resolve them.
Second, when there are multiple deconstructs, they cannot be used in one single active pattern because we cannot overload active patterns (unless allocating a list, and let the user pass in the number of parameters for the pattern)
Right, that's much better. To avoid clashing with an existing DU case, I'd prefer a new symbol for this new pattern matching construct, for example:
match x with | :? Node1 as ?( a: T, b: U ) -> ... // or, combining the two patterns: | :? Node2(x, y, z) -> ...
... where the second form is similar to the C#
I prefer this form, because it then fix the type to deconstruct from, which feels safer to write.