-
Notifications
You must be signed in to change notification settings - Fork 23
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
caseStmtMacros to support C#8-like Recursive Patterns matching (Deconstruction Pattern) #57
Comments
I think it's hard to support |
In a v2 I'd like to have assignment support when deconstructing, maybe via a special prefix symbol like case ("foo", 78)
of ("foo", @a): echo $(a*2) # prints 78 * 2 = 156
of ("bar", 88): echo "no"
else: discard |
@GULPF @Araq on second thought, let expr = ("foo", 78)
if expr.matches(("foo", _)): discard # matches a tuple of length 2
if expr.matches(("foo", )): discard # matches a tuple of length 1
if expr.matches("foo"): discard # same as if expr == "foo"
# works with matching against derived type, allowing also to capture derived instance
if expr.matches(Employee(name: "bob"), myderivedinstance): echo myderivedinstance.name # same as C# example `if (bassam is Employee {Name: "bob"} myderivedinstance)` this is not specific to when expr.matches(("foo", _)) : discard
doAssert expr.matches(("foo", _))
let ok = expr.matches(("foo", _)) implementationmacro matches(pattern: untyped) = untyped # will evaluate to bool
macro matches(pattern: untyped, capture: untyped) = untyped # will evaluate to bool and capture derived pattern in `capture`, as in C# and example above |
IMHO these proposals should start by providing a good example of current Nim code that would benefit from it. Is there something that gets written time and time again that would improve with this? (also including readability not only terseness when writing the code). I do think that deconstructing is a good tool though, but often times we just want to guard and alias to locals, which is an use case that can be solved more cleanly with something like this I think: if let a = ("foo", a):
echo $(a*2)
if let _ = ("foo", _): # `_` is just used to force deconstructuring
echo "hi!"
# from the original comment
# case let a, b = ("foo", 78)
# of ("foo", a): echo $(a*2) # referencing `b` would produce an error, not in scope
# of ("bar", c): echo "no" # error: `c` is not part of the case let statement
# else: discard
# this I think is better
case ("foo", 78)
of let a = ("foo", a): echo $(a*2)
of let _ = ("foo", _): echo "ok" # forced matching
of ("bar", 80): echo "no" # no destructuring or matching
else: discard Alternatively, a fully featured |
For reference also scheme's matchable is implemented as a macro and is quite flexible. |
Seems like Rust-like The most ergonomic pattern matching I came across was Haskell there are 2 syntaxes, unfortunately the nicer one does not fit Nim at all (though the second one is very similar to Nim's). Syntax 1: take 0 _ = []
take _ [] = []
take n (x:xs) = x : take (n-1) xs Syntax 2 take m ys = case (m,ys) of
(0,_) -> []
(_,[]) -> []
(n,x:xs) -> x : take (n-1) xs |
isn't this |
I like the https://github.com/nim-lang/Nim/issues/8649#issuecomment-413323627 idea, if one can capture a submatch Pattern matching is a big ergonomic win, there are so many @krux02 's macro in his ast pattern lib can also be made to work on runtime values, we just have to agree on some kind of standard API |
With the features that are already there in Nim I implemented recursive pattern matching fo AST nodes here: https://github.com/krux02/ast-pattern-matching. Please get to the point and explain why the given language features are not enough. The issue is just a compilation of random ideas and in general quite a mess. |
Whatever comes out of this, I would argue that it should be enough to support both patty and AST pattern matching (both suitably adapted) |
The problem is that both @andreaferretti 's patty and @krux02 's ast-pattern-matching currently lack a lot of features, but in a very different way: e.g.
now, I really want to have a working lib:
on the other hand the patty and the ast-pattern-matching dsl-s differ .. but not greatly. this means we might have two slightly different dsl-s for the same thing in an already small ecosystem. Do you guys want to compromise on a single api and somehow combine the two libs approaches into a single , more universal nim pattern matching lib? Such a lib can still be
I worked before on personal forks of both libs, but I couldn't decide which would be more feasible to adapt (and I didn't have time). I also planned to make my own match macro, but then we will just have 3 libs (insert xkcd standards comic) |
I would certainly want a library that generalize both patty and @krux02s' library. I am also not especially attached to patty: if a better library comes out that does pattern matching, I will be happy yo deprecate it. It was just a small experiment, but it is by no means a complete solution. |
so I decided to test my ideas in https://github.com/alehander42/gara @andreaferretti I got the idea for many features from patty , especially unification, I am thinking of a more powerful variant of it: e.g. support @timotheecour I also implemented your matches idea, but I am not sure about the API: I have |
Fusion pattern matching does not seem to have "custom matching" or "deconstruction", but it seems plenty sufficient for most pattern matching ( |
Agreed, I think this RFC has been superseded by #245. For "custom matching" or "deconstruction", most mechanisms can be customized (write procs to support object patterns, write an See also nim-lang/fusion#61. |
see https://gist.github.com/Araq/169d1e24b2b996d024a780ef6a4e6c09#file-casestmtmacros-nim for context, introduced by @Araq for a 1st version of this concept.
IT reminds me of Recursive Patterns matching (Deconstruction Pattern) in C#8, see https://www.infoq.com/articles/cs8-ranges-and-recursive-patterns
recursive could be handled later.
But supporting
_
placeholder is very useful, would be nice to support itfurthermore,EDIT see reply below; this is better handled with a regular macroif
could be handled as well, it should be no different fromcase
in terms of capabilities (ie introduce alsoifStmtMacros
)analog to how
if
andcase
both handle pattern matching in C#matches
where?
matchers.nim
links
snippet copied over from @Araq's post
The text was updated successfully, but these errors were encountered: