christhekeele
Calling all Matchspecs!
Hey all!
I’ve been working on an elixir-to-matchspec compiler. Think ex2ms with support for a few more expressions, pattern support, tracing support, helpful errors, and some other niceties.
Right now it’s passing ex2ms’s test suite, and I’ve added many tests of my own, but… I know I’ve seen edge cases where bad matchspecs were generated during development that I forgot to jot down. Also, I’d love to see it build other matchspecs used in the field that people have crafted by hand!
So, it’d be incredibly helpful if anyone cared to share theirs to bolster my test suite! I’m interested in:
- matchspecs passed to
:ets.select...:recon_trace.calls/2Registry.select/2:dbg.tp...:erlang.trace_pattern...
- matchpatterns passed to
:ets.match...Registry.match/4
- especially anything with
- non-trivial destructuring in the match heads
- nested tuple literals in match bodies
All contributions greatly appreciated! ![]()
Most Liked
mguilmineau
A few samples from our code - hope it helps.
:ets.select( ets_name( customer ), [ { { { customer, :_ }, { true, :“$1”, :_, :“$2” } },
[ { :andalso,
{ :“==”, {:map_get, :a, {:map_get, :job, :“$2”}}, a},
{ :“==”, {:map_get, :b, {:map_get, :job, :“$2”}}, b}
} ],
[ [:“$1”, :“$2”] ] } ] )
:ets.select_delete( ets_name( customer ), ( for task_id ← task_ids,
do: { { { customer, :_ }, :“$1” }, [ { :“==”, {:map_get, :id, :“$1”}, task_id } ], [:true] } ) )
:ets.select( ets_name( customer ),
[ { { { customer, :_ }, { :, :“$1”, :, :“$2” } },
[ { :andalso,
{ :“>=”, :“$1”, Util.to_dets( date ) },
{ :“<”, :“$1”, Util.to_dets( Util.tomorrow ) }
} ],
[ :“$2” ] } ] )
:ets.select( ets_name( customer ),
[ { { { customer, :_ }, :“$1”, :“$2”, :, : },
[ { :or,
{ :“==”, {:map_get, :reattempt, :“$1”}, @auto },
{ :“==”, {:map_get, :reattempt, :“$1”}, @manual }
} ],
[ :“$1” ] },
{ { { customer, :_ }, :“$1”, @paused, :, : },
,
[ :“$1” ] },
{ { { customer, :_ }, :“$1”, @deleted, :, : },
,
[ :“$1” ] },
( if for_seeding,
do: { false, , [ true ] },
else: { { { customer, :_ }, :“$1”, :, :, true },
,
[ :“$1” ] } )
] )
christhekeele
I feel as if this is 50/50, personally.
- Match specs are already an informal, loosely-documented sort-of-erlang-AST. They are difficult to debug and error prone.
- The approach I am taking resolves this, as all specs are validated against erlang’s builtin ms test functions at compile time.
- Traversing an even wider conceptual gap from sort-of-erlang-AST to Elixir just adds to the cognitive load in writing, debugging, and maintaining them.
- The approach I’m taking passes all code through the Elixir compiler first, to throw all the familiar errors and warnings, before converting Elixir code into specs.
This is my real goal: not to solve these kinds of problems, but to make match specs more accessible, and therefore increase their adoption in general, so that more advanced tooling can be easily built on top of them without needing to understand the underlying syntax. What I’m working on was originally a proposal to the language itself, though I feel like it belongs outside it now.
Of course, targeting Elixir AST as the high-level format should help with this a lot: library authors can just leverage Elixir’s powerful macro system to translate things (ex: mnesia schemas, ecto schemas, ets queries) from Elixir code, to Elixir code. Then my library can handle all the fussy details of whether or not it’s a viable match spec without requiring further knowledge.
Not quite sure I understand here—are you saying that you have a known set of ids on hand you want to retrieve verbatim, and doing a single :ets.select/2 call with a match spec is not as efficient as a series of :ets.lookup/2 calls or a single :ets.match/2 call with a match pattern?
mguilmineau
I support your effort and I hope I wasn’t giving a different impression. match specs are not intuitive, too different from elixir syntax and little discussed on the web. The pre-compilation validation is a welcome addition. The detailed match specs we currently have look unnecessarily intimidating. There is value in this effort.
My comment on full scan: we tend to duplicate values in :ets storage with keys designed to match the queries we run frequently, so as to use lookup or match instead of more complicated and slower select match specs. In other words, while we do use match specs they tend to be a temporary stop gap but eventually get simpler or are removed entirely, primarily for performance reasons.
Last Post!
christhekeele
Excellent, I love me some edge cases!
I didn’t know that! I’ll have to play around with this form to see if it is a potential optimization.
I think this is a case of holistic term ordering, a standard caveat of comparison operators on the BEAM. Sadly there’s not much my compiler can do to “correct” this, but I hope that by passing all MS code thru the Elixir compiler first it will benefit from the new typing warnings coming to comparisons. I need to play around with how those intersect…
That’s slick! I’m pretty sure my compiler supports emitting map literals straight out of an MS but definitely should make sure that’s in the test cases.
Popular in Discussions
Other popular topics
Chat & Discussions>Discussions
Latest on Elixir Forum
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









