CARVIEW |
Select Language
HTTP/2 302
server: nginx
date: Fri, 08 Aug 2025 20:12:16 GMT
content-type: text/plain; charset=utf-8
content-length: 0
x-archive-redirect-reason: found capture at 20180611010626
location: https://web.archive.org/web/20180611010626/https://github.com/ujihisa/matchmaker
server-timing: captures_list;dur=0.744881, exclusion.robots;dur=0.032956, exclusion.robots.policy;dur=0.019023, esindex;dur=0.012193, cdx.remote;dur=45.738418, LoadShardBlock;dur=377.614159, PetaboxLoader3.datanode;dur=123.474650, PetaboxLoader3.resolve;dur=193.576276
x-app-server: wwwb-app28
x-ts: 302
x-tr: 460
server-timing: TR;dur=0,Tw;dur=0,Tc;dur=0
set-cookie: wb-p-SERVER=wwwb-app28; path=/
x-location: All
x-rl: 0
x-na: 0
x-page-cache: MISS
server-timing: MISS
x-nid: DigitalOcean
referrer-policy: no-referrer-when-downgrade
permissions-policy: interest-cohort=()
HTTP/2 200
server: nginx
date: Fri, 08 Aug 2025 20:12:17 GMT
content-type: text/html; charset=utf-8
x-archive-orig-server: GitHub.com
x-archive-orig-date: Mon, 11 Jun 2018 01:06:27 GMT
x-archive-orig-transfer-encoding: chunked
x-archive-orig-status: 200 OK
x-archive-orig-cache-control: no-cache
x-archive-orig-vary: X-PJAX
x-archive-orig-set-cookie: logged_in=no; domain=.github.com; path=/; expires=Fri, 11 Jun 2038 01:06:27 -0000; secure; HttpOnly
x-archive-orig-set-cookie: _gh_sess=SVZObTNHQTAwUlgxUGJXNndDWVdSY1NCMzZZL1dFUmlSL3R0amVVVkNGUlNCOFVZMXBDeno3S2NOZkR0c2orcHV0cXRvVXA0WWx6ai9wRTNXWElYSXhrTktYSlpQMnBGYXF5S1liMTYxcEJTTXVwQmhoV3dmR0h6RklWRkVlOHdlcnJZQ3k3MWpzdHVJSjFFNGhnWnMrZnJBN01mUVBocms5ejFmeGRZMlRINUY4QmhzZU0remQ3aHYySGo1UGxYRzF6T3Z5MlhMU2RzVkkrT2xXb3BYdTdOZmZjTkFGdEFQQSt3dzJGNDdKV2VrbTF2V0liODlVbmFlNGMrQ05GdlJ3SXBzeE9lMFNNTmliZzdhWHdTcWtZZVE4dWNscVZ1K0NVeFI4c3NhSmI1c1EzaEFkMlJ1L1ZTaEd6V1RndnBSdjZZOVBRRFBleXRkUWw2SkwrcStFNDl4aHFNOE5GYUU5R2dwL0xMRTJzTTF3cnFHR0p3Wk1QekJNQzhkV3lyKy93WjlHNTlralpERUs3Z25OSzBWdmhaUDNmbHJuTkN0NnhZOUV3UjljUT0tLWRqSHQvbmJocUJWR3llbWxSaDM2SVE9PQ%3D%3D--725b6e22b9c7b8540174c7e74056616c2d99812c; path=/; secure; HttpOnly
x-archive-orig-x-request-id: 69fa90db-1c10-4b46-b3be-6bd0469ff5d3
x-archive-orig-x-runtime: 0.285553
x-archive-orig-strict-transport-security: max-age=31536000; includeSubdomains; preload
x-archive-orig-x-frame-options: deny
x-archive-orig-x-content-type-options: nosniff
x-archive-orig-x-xss-protection: 1; mode=block
x-archive-orig-expect-ct: max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"
x-archive-orig-content-security-policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; connect-src 'self' uploads.github.com status.github.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; frame-src render.githubusercontent.com; img-src 'self' data: assets-cdn.github.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; manifest-src 'self'; media-src 'none'; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com
x-archive-orig-x-runtime-rack: 0.292808
x-archive-orig-x-github-request-id: E870:2131:535511A:9559B7B:5B1DCB12
x-archive-guessed-content-type: text/html
x-archive-guessed-charset: utf-8
memento-datetime: Mon, 11 Jun 2018 01:06:26 GMT
link: ; rel="original", ; rel="timemap"; type="application/link-format", ; rel="timegate", ; rel="first memento"; datetime="Mon, 11 Jun 2018 01:06:26 GMT", ; rel="memento"; datetime="Mon, 11 Jun 2018 01:06:26 GMT", ; rel="next memento"; datetime="Fri, 22 Jan 2021 13:10:01 GMT", ; rel="last memento"; datetime="Fri, 22 Jan 2021 13:10:01 GMT"
content-security-policy: default-src 'self' 'unsafe-eval' 'unsafe-inline' data: blob: archive.org web.archive.org web-static.archive.org wayback-api.archive.org athena.archive.org analytics.archive.org pragma.archivelab.org wwwb-events.archive.org
x-archive-src: archiveteam_github_20180703235326/archiveteam_github_20180703235326.megawarc.warc.gz
server-timing: captures_list;dur=0.806846, exclusion.robots;dur=0.040634, exclusion.robots.policy;dur=0.025129, esindex;dur=0.012040, cdx.remote;dur=63.451350, LoadShardBlock;dur=735.124005, PetaboxLoader3.datanode;dur=188.303776, PetaboxLoader3.resolve;dur=691.822989, load_resource;dur=214.825235
x-app-server: wwwb-app28
x-ts: 200
x-tr: 1160
server-timing: TR;dur=0,Tw;dur=0,Tc;dur=1
x-location: All
x-rl: 0
x-na: 0
x-page-cache: MISS
server-timing: MISS
x-nid: DigitalOcean
referrer-policy: no-referrer-when-downgrade
permissions-policy: interest-cohort=()
content-encoding: gzip
GitHub - ujihisa/matchmaker: A Ruby Pattern Matching Library
Fetching latest commit…
Permalink
ujihisa/matchmaker forked from hayeah/matchmaker
Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
A Ruby Pattern Matching Library
Ruby
Clone or download
Launching GitHub Desktop...
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop...
If nothing happens, download GitHub Desktop and try again.
Launching Xcode...
If nothing happens, download Xcode and try again.
Launching Visual Studio...
If nothing happens, download the GitHub extension for Visual Studio and try again.
Pull request
Compare
This branch is 1 commit ahead, 9 commits behind hayeah:master.

Cannot retrieve the latest commit at this time.
Failed to load latest commit information. | |||
![]() |
lib | ||
![]() |
spec | ||
![]() |
.document | ||
![]() |
.gitignore | ||
![]() |
LICENSE | ||
![]() |
README | ||
![]() |
Rakefile | ||
![]() |
VERSION | ||
![]() |
matchmaker.gemspec |
README
Matchmaker is a powerful and expressive DSL that brings pattern matching into Ruby. Often we need to check if an object is what we expect, and if so, we want to take it apart. Pattern matching is an expressive idiom from functional programming languages to make checking on an object and taking it apart concisely readable. h1. Install > sudo gem install hayeah-matchmaker > irb -rubygems irb> require 'matchmaker' irb> Case(1) { of(1) } # => true h1. Case Statement A case statement can have many alternative patterns to match. The patterns are run in sequence until the first one that matches. If no pattern matches, a Case::NoMatch exception is raised. Case(1) { of(1) of(:b) } # => true Case(2) { of(1) of(:b) } # => raise Case::NoMatch Case(:b) { of(1) of(:b) } # => true Matchmaker uses the Case DSL to build a runnable pattern matcher. You can store the pattern matcher in a constant or variable, so Matchmaker doesn't have to build it everytime you use it. c = Case.new { of(1) of(:b) } c.match(1) => true c.match(0) => Case::NoMatch c.match(:b) => true For each pattern in the case statement, there can be an action associated with it. The action is run when the pattern of that branch matches, and the result of the action returned: c = Case.new { of(1) { :a } of(2) { :b } of(3) # { true } by default } c.match(1) # => :a c.match(2) # => :b c.match(3) # => true h1. Simple Patterns Literals ruby objects are matched by == of(1) # matches 1 of(:a) # matches :a of("a") # matches "a" A regex is used to match string of(/abc/) # matches "0abc0" A class is used to match objects of the that class of(String) # matches "abc" A range can be used to match a range of integers of(1..10) # matches integer within 1 and 10 An array should be an array of patterns that matches an array object, such that each element in the array should match its pattern. of([String,Array,Hash]) # matches ["a",[],{}] h1. Destructuring and Pattern Guard There are patterns to match common ruby objects. For example, Case#string is a method of the DSL to build the string pattern. of(string) # matches any string of(string("a")) # matches "a" of(string(/foo/)) # matches any string of that regexp These pattern methods can make variable bindings of the matched object, Case([1,"a"]) { of([1,string(/a/,:a)]) { a } } # => "a" In this example, the pattern sets the variable ':a' to the matched string. These variables are actually bindings. Binding of the same name in different patterns must equal to each other, otherwise the overall pattern won't match. c = Case.new { of([string(/a/,:a),string(/b/,:a)]) } c.match(["ab","ab"]) # => true c.match(["ab","ba"]) # Case::NoMatch A guard is an arbitray ruby block associated with a pattern, so that a pattern matches iff the guard returns true. c = Case.new { of(string(/a/) {|s| s.length == 2 }) } c.match("ab") # => true c.match("ba") # => true c.match("abc") # Case::NoMatch h1. Value Patterns These patterns are used to match a single Ruby object. See later for structural patterns for ways to combine these value patterns. All these methods can make binding and take a guard, as in of(some_pattern(pattern_spec,:binding) {|matched_value| some_more_test_on(matched_value) }) h2. Case#_ This is the wildcard that matches anything of(_) You can use binding to say "I don't care what this and that are, but I want them to be the same", like so, of([_(:a),1,_(:a)]) The pattern matcher binds whatever matches the first and last element of the array to ":a", the binding fails unless those elements are the same. h2. Case#a Matches any object of a class. of(a(String)) h2. Case#literal Matches an object by its "==" method. of(literal(1)) of(literal(:b)) h2. Case#integer Matches an integer. of(integer) # any integer of(integer(1)) # matches 1 of(integer(1..10)) # matches a range of(integer([1,3,5,7,9])) # matches any number in the set h2. Case#string of(string) of(string("abc")) of(string(/abc/)) h2. Case#symbol of(symbol) of(symbol(:abc)) of(symbol(/abc/)) # matches a symbol if its to_s matches the regexp. h1. Structural Patterns For "container" objects like arrays and hashes, pattern matching is a nice way to specify the properties of the object, and taking it apart. h2. Case#array of([]) # == of(array([])) of([1,2]) # matches exactly [1,2] of([symbol,string,symbol]) # matches an array the first and last element are # the same symbol, the second element is a string of([symbol(nil,:a),string,symbol(nil,:a)]) You can match the tail of an array by using the special method Case#_! c = Case.new { of([1,2,_!(integer)]) } c.match([1]) # Case::NoMatch c.match([1,2]) # => true c.match([1,2,3]) # => true c.match([1,2,3,4,5]) # => true c.match([1,2,3,:a]) # => Case::NoMatch this pattern matches any array whose first two elements are 1 and 2, the rest are integers. h2. Case#hash Hashes are pattern matched by specifying the what pattern a key's value should match. A key can be either be required, or optional, for the pattern matching to succeed. c = Case.new { of("required" => integer, ["optional"] => string) } c.match("required" => 10, "optional" => "a") # => true c.match("required" => 10, "optional" => 1) # Case::NoMatch c.match("required" => 10) # => true c.match("required" => "a") # => Case::NoMatch The optional key is denoted by wrapping that in an array. h1. Higher Order Pattern The pattern matcher is just constructed with a bunch of objects. So it's possible to save a pattern in a variable, and use that to build larger patterns. Build a two element array of a custom pattern, c = Case.new { my_pattern = [symbol,string] of([my_pattern,my_pattern]) } Generate pattern with lambda, c = Case.new { pattern = lambda {|pattern1,pattern2| [pattern1,pattern2]} of(pattern.call(symbol,string)) of(pattern.call(string,symbol)) } h2. Case#is This method is used to coerce an object into pattern if it isn't already. is(/regexp/) # string(regexp) is(some_class) # matches by class is(obj) # literal(obj) for any object Mostly useful for higher order stuff you are doing. h2. Case#bind This is used to matched values to variables. It takes a pattern, and a binding name, and possibly a guard. c = Case.new { foo = is([string]) of(bind(foo,:a)) { [1,a] } of(bind([foo],:a)) { [2,a] } } c.match(["a"]) # => [1,["a"]] c.match([["a"]]) # => [2,[["a"]]]
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session.
You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.