README.md

# 🍵 Matcha

<!-- MODULEDOC BLURB -->

> **_First-class match specification tooling for Elixir._**

<!-- MODULEDOC BLURB -->

[![Version][hex-pm-version-badge]][hex-pm-versions]
[![Downloads][hex-pm-downloads-badge]][hex-pm-package]
[![Documentation][docs-badge]][docs]
[![Dependencies][deps-badge]][deps]
[![License][hex-pm-license-badge]][hex-pm-package]

|         👍         |                  [Test Suite][suite]                  |                   [Test Coverage][coverage]                    |
| :----------------: | :---------------------------------------------------: | :------------------------------------------------------------: |
| [Release][release] | [![Build Status][release-suite-badge]][release-suite] | [![Coverage Status][release-coverage-badge]][release-coverage] |
|  [Latest][latest]  |  [![Build Status][latest-suite-badge]][latest-suite]  |  [![Coverage Status][latest-coverage-badge]][latest-coverage]  |

#### Installation

`Matcha` is distributed via [hex.pm][hex-pm], you can install it with your dependency manager of choice using the config provided on its [hex.pm package][hex-pm-package] listing.

#### Documentation

Complete documentation including guides are hosted online on [hexdocs.pm][docs].

## Usage

### Synopsis

<!-- MODULEDOC SNIPPET -->
<!--
  all hyperlinks in this snippet must be inline,
  rather than using markdown link references
-->

`Matcha` offers tight integration with Elixir and match specifications.

Match specifications are a BEAM VM feature that executes **_simple_** pattern matching operations very close-to-the-metal, _often several thousand times more performant than a comparable `Enum` operation_. They can be used to efficiently:

- [filter/map in-memory data](https://www.erlang.org/doc/man/ets.html#match_spec_run-2)
- [find ETS objects](https://erlang.org/doc/man/ets.html#select-2)
- [trace specific function calls](https://erlang.org/doc/man/dbg.html#tp-2)

However, they are notoriously difficult to compose and use. Matcha makes this intuitive with ergonomic macros and a fluent API with which to manipulate them.

### Examples

```elixir
require Matcha

# Turns Elixir code into a match specification
iex> spec = Matcha.spec do
...>   {x, y, z} -> x + y + z
...> end
...> spec.source
[{{:"$1", :"$2", :"$3"}, [], [{:+, {:+, :"$1", :"$2"}, :"$3"}]}]
```

For more information, check out [the interactive usage guides](https://hexdocs.pm/matcha/usage.html#content), including using Matcha for:

- [filtering & mapping data](https://hexdocs.pm/matcha/usage/filtering-and-mapping.html#content)
- [selecting objects from tables](https://hexdocs.pm/matcha/usage/tables.html#content)
- [tracing function calls](https://hexdocs.pm/matcha/usage/tracing.html#content)

<!-- MODULEDOC SNIPPET -->

## Design

### Goals

Matcha aims to make it easy to use match specs in Elixir. This includes:

- Passing through the Elixir compiler to get familiar errors and warnings.
- Raising with informative error messages where we can, and friendlier ones when surfacing erlang errors.
- Providing high-quality documentation on not just Matcha usage, but match specs and their use-cases in general.
- Offering high-level APIs around match spec usage so it is trivial to leverage their power.
- Defining concrete implementations of the 'virtual' function calls for better documentation, compile-time check, and typechecking integration.

## Contributing

Contributions are welcome! Check out the [contributing guide][contributing] for more information, and suggestions on where to start.

## Support

Matcha strives to support all maintained combinations of Elixir and erlang/OTP. The full list of supported combinations is available by checking the latest successful [test matrix run][test-matrix].

Since it pokes around in compiler internals, it is important to get ahead of upstream changes to the language. This is accomplished with [nightly builds][test-edge] against the latest versions of Elixir, erlang/OTP, and dependencies; which catches issues like [internal compiler function signature changes](https://github.com/christhekeele/matcha/commit/27f3f34284349d807fcd2817a04cb4628498a7eb#diff-daf93cf4dc6034e9862d0d844c783586210ea822ae6ded51d925b0ac9e09766bR31-R43).

<!-- LINKS & IMAGES -->

<!-- Hex -->

[hex-pm]: https://hex.pm
[hex-pm-package]: https://hex.pm/packages/matcha
[hex-pm-versions]: https://hex.pm/packages/matcha/versions
[hex-pm-version-badge]: https://img.shields.io/hexpm/v/matcha.svg?maxAge=86400&style=flat-square
[hex-pm-downloads-badge]: https://img.shields.io/hexpm/dt/matcha.svg?maxAge=86400&style=flat-square
[hex-pm-license-badge]: https://img.shields.io/badge/license-MIT-7D26CD.svg?maxAge=86400&style=flat-square

<!-- Docs -->

[docs]: https://hexdocs.pm/matcha/index.html
[docs-guides]: https://hexdocs.pm/matcha/usage.html#content
[docs-badge]: https://img.shields.io/badge/documentation-online-purple?maxAge=86400&style=flat-square

<!-- Deps -->

[deps]: https://hex.pm/packages/matcha
[deps-badge]: https://img.shields.io/badge/dependencies-1-blue?maxAge=86400&style=flat-square

<!-- Status -->

[suite]: https://github.com/christhekeele/matcha/actions?query=workflow%3A%22Test+Suite%22
[coverage]: https://coveralls.io/github/christhekeele/matcha

<!-- Release Status -->

[release]: https://github.com/christhekeele/matcha/tree/release
[release-suite]: https://github.com/christhekeele/matcha/actions?query=workflow%3A%22Test+Suite%22+branch%3Arelease
[release-suite-badge]: https://img.shields.io/github/checks-status/christhekeele/matcha/release.svg?maxAge=86400&style=flat-square
[release-coverage]: https://coveralls.io/github/christhekeele/matcha?branch=release
[release-coverage-badge]: https://img.shields.io/coveralls/christhekeele/matcha/release.svg?maxAge=86400&style=flat-square

<!-- Latest Status -->

[latest]: https://github.com/christhekeele/matcha/tree/latest
[latest-suite]: https://github.com/christhekeele/matcha/actions?query=workflow%3A%22Test+Suite%22+branch%3Alatest
[latest-suite-badge]: https://img.shields.io/github/checks-status/christhekeele/matcha/latest.svg?maxAge=86400&style=flat-square
[latest-coverage]: https://coveralls.io/github/christhekeele/matcha?branch=latest
[latest-coverage-badge]: https://img.shields.io/coveralls/christhekeele/matcha/latest.svg?maxAge=86400&style=flat-square

<!-- Other -->

[elixir-version-requirements]: https://hexdocs.pm/elixir/Version.html#module-requirements
[changelog]: https://hexdocs.pm/matcha/changelog.html
[test-matrix]: https://github.com/christhekeele/matcha/actions/workflows/matrix.yml
[test-edge]: https://github.com/christhekeele/matcha/actions/workflows/edge.yml
[contributing]: https://hexdocs.pm/matcha/contributing.html