pattern.cr
Version, currently main branch1 version
- main branchlatestFeb 27, 2021
github.com/HertzDevil/pattern.cr
Runtime structural pattern matching macros
7 stars
0 dependents
License: MIT
Installation
# Add this to your shard.yml
dependencies:
pattern.cr:
github: HertzDevil/pattern.cr
branch: mainmain is a branch, not a release, so this tracks it rather than pinning a version.
Then run:
shards installshard.yml
- Crystal
0.36.0- License
- MIT
- Author
- Quinton Miller <nicetas.c@gmail.com>
Dependencies
This version declares no dependencies.
README
# pattern.cr
Structural pattern matching proof-of-concept library
## Usage
Due to syntax restrictions, macro arguments must be valid Crystal expressions
and cannot declare new variables, and features like splats in container literals
are not supported (but see
[crystal-lang/crystal#3718](https://github.com/crystal-lang/crystal/issues/3718)). The following conventions are applied in this library:
* `exp ~>? pat` becomes `Pattern.matches?(exp, pat)`. Flow typing will not work
properly because the bound variables in `pat` must be declared prior to this
point; use `Pattern.try_match(exp, pat)` in those cases instead.
* `exp ~> pat` becomes `Pattern.match!(exp, pat)`. Flow typing works here due to
the exception thrown in the failing branch.
* `*x` in array patterns are replaced with `__splat(x)`. The `__splat` doesn't
need to be an existing method.
* `**x` in hash patterns are replaced with `__double_splat => x`. Note that
`NamedTuple` patterns cannot have a double splat in this way.
Refer to the same examples in [`SPEC.md`](SPEC.md#Examples) to see how compiler
support for structural pattern matching would look like. See also the
[known limitations](SPEC.md#Known-limitations).
```crystal
# Before
ary = [1, 2, 3, 4, 5, 6, 7]
if ary.size >= 2
a, b = ary
rest = ary[2..]
else
raise "not enough elements"
end
# After
require "pattern"
a, b, rest = nil, nil, nil
Pattern.match! [1, 2, 3, 4, 5, 6, 7], [a, b, __splat(rest)]
```
```crystal
# Before
if ary.size == 3
first, x, y = ary
end
if first.is_a?(Circle) && x.is_a?(Int32) && y.is_a?(Int32)
first.move_to(x, y)
end
# After
require "pattern"
first = nil
x = nil
y = nil
Pattern.try_match(ary, {first = Circle, x = Int32, y = Int32}) do
first.move_to(x, y)
end
```
```crystal
# Before
anniversary = events.find do |ev|
ev.has_key?("start") && ev["start"].in?("2020-01-01".."2020-12-31") &&
ev.has_key?("id") && ev["id"] =~ /^ANNIV.*/
end["start"]
events.select! &.[]?("start").== anniversary
# After
require "pattern"
anniversary = nil
Pattern.match!(events, {__splat(_), {
"start" => anniversary = "2020-01-01".."2020-12-31",
"id" => /^ANNIV.*/,
}, __splat(_)})
events.select! do |ev|
Pattern.matches?(ev, {"start" => __pin(anniversary)})
end
```
## Installation
1. Add the dependency to your `shard.yml`:
```yaml
dependencies:
pattern:
github: HertzDevil/pattern.cr
```
2. Run `shards install`
## Contributing
1. Fork it (<https://github.com/HertzDevil/pattern.cr/fork>)
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request
## Contributors
* [Quinton Miller](https://github.com/HertzDevil) - creator and maintainer
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This branch
- Branch
main- Seen
- Feb 27, 2021
- Crystal
0.36.0- Indexed
- yes
Dependents
No indexed shard depends on this one yet.
Repository
github.com/HertzDevil/pattern.cr
Metadata
- Created
- Aug 12, 2026
- Updated
- Aug 13, 2026
- Synced
- Aug 13, 2026
- Versions
- 1