-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Type-directed matching for x::xs and related list syntax #1088
Comments
It would be great if this worked on Span<T> or Memory<T>. |
I think we'd have to flesh out support in the RFC/Implementation, but it seems reasonable to allow something like this on anything that supports an integral indexer, which I think includes Span/Memory. Definitely something to dig into though. |
Right, and I would consider that a vital inclusion in this feature, as it would allow you to avoid the overhead of allocating a new array everytime you use it. Suddenly, it makes traversing through arrays in this way a zero-cost abstraction. |
I'm actually almost more inclined to deprecate It seems to me there are very few types that support copy-free functional one-element construction and decomposition. Which is what the syntax Things like Span and Memory use indexing, we don't really want to be making new Spans and Memory all the time do we? |
I'd be in support of something like Cons as shown here too, I just want a unified and efficient way to abstract across collections/containers. I went with x::xs and the related lists syntaxes at first because they are the friendliest/nicest to use. |
Hmmm If we went for In your example at the top what is I think what you're wanting (list-style functional decomposition of other collections) just isn't really possible (or where it is it's not really optimal). Lists are a particularly strange thing in this regard and it's why they've always been so popular since Lisp. |
I could imagine a list-style decomposition for an array where the "tail" |
C# 11 will likely ship some form of this in their list patterns. Highlights include:
That's a really nice set of rules overall, the one that is the least-doable in F# through some non-compiler-change mechanism is the 'spread pattern'. |
I'm not totally thrilled about adding list patterns to a language, nor indeed most pattern sugar. For list patterns, I think their performance can be really subtle, especially for immutable structures - is the middle copied out or not? That depends very much on whether the data structure supports copy-free inspection into its internals, which in turn likely rest on quite complex and subtle uses of Span and Memory (or simply can't be done at all). The F# position (also OCaml, and to some extent Haskell) has historically been to avoid the somewhat addictive temptation to add pattern sugar and, for F#, to instead ask users to put all such complexity into active patterns. Active pattern definitions are "normal code" and don't require particularly deep knowledge about how pattern syntax is de-sugared (it's fairly obvious) and can be read "forwards" just like the rest of code. They also encourage the user to write patterns at an appropriate semantic level (for example, combining multiple nested patterns representing a semantic categorization of, say, a list of strings, into one active pattern). Still, I hear what you're saying @baronfel . It's just I also expect a bit of a backlash to C# list pattern syntax over time, and have long been cautious about adding it to F# for the reasons above. |
For some reasons, C# seems to be going totally the other way, with predicates that can be expressed in terser way, in some cases, than the F# way (to put all complex stuff behind C# approach seems, in general, to enable some deduplication but I haven't played with it to really get the feel of it. I also remember, hearing from seasoned haskell developers, that leaning a lot on pattern matching (and DU) had it's limitations in terms of design, because it lead to some possible duplication, when things are matched over and over again. I also favor caution, as to extend pattern constructs, it would be ok, to see how much C# code start using the feature, and if practially speaking, an active pattern is not good enough, for now, until we know more. |
For what's it is worth I am also in favour of a cautious approach. I watch C# feature explosion in pattern matching and wonder if in 2025 the language spec for C# pattern matching will be bigger than for the rest of the language put together. Seems to me that more generic solutions like Active Patterns are preferable over adding a lot of special cases in the language spec. |
I think a generic mechanism comes in handy when working with collections like a |
Personally, I have no problems writing active patterns for matching on various collections, but as far as I can see, they won't work well for Span, or other byrefs. Since those can only be wrapped in other byrefs, and neither Option, or ValueOption, or Choice are byreflike. |
Perhaps a good compromise would be the ability to write user-defined active pattern infix operators, bonus points if they're overloadable (probably via SRTP) I'm sure there's already a suggestion for that... |
I couldn't agree more. |
I propose we change the behavior of the
::
syntax as it relates to pattern matching when used with a non-list type. This in my mind is the logical sibling of #1086, mirroring those goals at the destruction-side of things rather than the construction-side.The existing way of approaching this problem in F# is to use other type-specific syntax for matching, like
[| x |]
for a single element array, but this has a few problems:xs
in the first match case above)Pros and Cons
The advantages of making this adjustment to F# are
The disadvantages of making this adjustment to F# are
rest
pattern for non-list typesxs
anarray
? if so, how does each iteration create an entirely new array? this would be bad for allocation IMO.rest
pattern's output couldn't be passed in to the recursive function itself::
meanslist
and onlylist
. after this change additional context would be required for a reader.Extra information
Estimated cost (XS, S, M, L, XL, XXL): M
Related suggestions: (put links to related suggestions here): #1086
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply:
For Readers
If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.
The text was updated successfully, but these errors were encountered: