{"id":15069796,"url":"https://github.com/strangepleasures/matchmetender","last_synced_at":"2026-01-03T03:50:35.811Z","repository":{"id":57723414,"uuid":"85757822","full_name":"strangepleasures/matchmetender","owner":"strangepleasures","description":"Pattern matching for Java","archived":false,"fork":false,"pushed_at":"2017-05-16T22:36:19.000Z","size":23,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-22T19:48:31.780Z","etag":null,"topics":["functional-programming","java","java8","pattern-matching"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/strangepleasures.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-21T22:00:05.000Z","updated_at":"2024-03-25T12:53:59.000Z","dependencies_parsed_at":"2022-08-25T13:02:16.890Z","dependency_job_id":null,"html_url":"https://github.com/strangepleasures/matchmetender","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strangepleasures%2Fmatchmetender","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strangepleasures%2Fmatchmetender/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strangepleasures%2Fmatchmetender/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strangepleasures%2Fmatchmetender/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/strangepleasures","download_url":"https://codeload.github.com/strangepleasures/matchmetender/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243838004,"owners_count":20355970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","java","java8","pattern-matching"],"created_at":"2024-09-25T01:44:44.542Z","updated_at":"2026-01-03T03:50:35.753Z","avatar_url":"https://github.com/strangepleasures.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Match me tender - a simple pattern matching DSL for Java\n\n### How to use\nTo include Match Me Tender into your project add a Maven dependency\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003ecom.github.strangepleasures\u003c/groupId\u003e\n\t\u003cartifactId\u003ematchmetender\u003c/artifactId\u003e\n\t\u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\nMost of the time the only class you need is *com.github.strangepleasures.match.Match*. Importing it with star import enables using it's methods as a DSL:\n```java\nimport static com.github.strangepleasures.match.Match.*;\n```\nThe core of Match Me Tender is two overloaded *match* methods:\n```java\npublic static \u003cT\u003e void match(T value, MatchingConsumer\u003c? extends T\u003e... consumers) { ... }\npublic static \u003cT, R\u003e R match(T value, MatchingFunction\u003c? extends T, ? extends R\u003e... functions) { ... }\n```\nThe first form accepts a value to match and a number of *MatchingConsumer* lambdas. When called *match* determines the type of the provided value and passes it to the first consumer with an appropriate signature (if any). A consumer wihout an explicit type (e.g. *(unknown) -\u003e ...*) matches any non-null value. \nThis form can be useful for handling multiple message types in Akka actors:\n```java\npublic void onReceive(Object message) throws Exception {\n\tmatch(message, // a value to match\n\t\t(Foo foo) -\u003e { \n\t\t\tlog.info(\"received a Foo: \" + foo); \n\t\t\tonFoo(foo);\n\t\t}, \n\t\t(Bar bar) -\u003e log.info(\"received a Bar: \" + bar),\n\t\t(Baz baz) -\u003e log.info(\"received a Baz: \" + baz),\n\t\t(unknown) -\u003e unhandled(unknown)\n\t); // this form doesn't return a value\n}\n```\nAnother *match* method has a similar semantics but accepts a list of lambda functions instead of consumers and returns a result from the matching function (or *null* if the value doesn't match any signature).\n```java\nString description = match(message, \n\t(Foo foo) -\u003e \"It's a Foo\", \n\t(Bar bar) -\u003e \"It's a Bar\",\n\t(Baz baz) -\u003e \"It's a Baz\",\n\t(unknown) -\u003e \"I don't know what it is\"\n); \n```\nIn addition to the simple class-based matching described above, it's also possible to perform value- or condition-based matching. A family of *on* methods allows to create *MatchingConsumer*s and *MatchingFunction*s checking additional conditions:\n```java\npublic static \u003cT\u003e MatchingConsumer\u003cT\u003e on(MatchingFunction\u003cT, Boolean\u003e filter, MatchingConsumer\u003c? super T\u003e action) { ... }\npublic static \u003cT, R\u003e MatchingFunction\u003cT, R\u003e on(MatchingFunction\u003cT, Boolean\u003e filter, MatchingFunction\u003c? super T, R\u003e mapper) { ... }\npublic static \u003cT\u003e MatchingConsumer\u003cT\u003e on(T expected, Runnable runnable) { ... }\npublic static \u003cT, R\u003e MatchingFunction\u003cT, R\u003e on(T expected, RunnableSupplier\u003cR\u003e supplier) { ... }\n```\nThis simple example explains how to use *match* in combination with *on*:\n```java\npublic static String classify(Integer value) {\n\treturn match(value,\n\t\ton(null, () -\u003e \"Null\"), \t // value-based, the only way to match null\n\t\ton(n -\u003e n \u003c 0, n -\u003e \"Negative\"), // conditional\n\t\ton(0, () -\u003e \"Zero\"),             // value-based\n\t\tn -\u003e \"Positive\"                  // you can mix \"on\" conditions with simple lambdas\n\t);\n}\n```\n### Modification of local variables in the enclosing environment\nA family of *com.github.strangepleasures.refs* classes allows you to modify local variables outside of *match* statements:\n```java\npublic static void countFruits(List\u003cFruit\u003e fruits) {\n\tIntRef apples = new IntRef(0);  // Effectively final but mutable!\n\tIntRef pears  = new IntRef(0);\n\tfruits.forEach(fruit -\u003e match(fruit,\n\t\t(Apple apple) -\u003e apples.value++,\n\t\t(Pear   pear) -\u003e pears.value++\n\t));\n\tSystem.out.println(\"Found \" + apples.value + \" apples and \" + pears.value + \" pears.\");\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrangepleasures%2Fmatchmetender","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstrangepleasures%2Fmatchmetender","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrangepleasures%2Fmatchmetender/lists"}