{"id":17195965,"url":"https://github.com/npryce/maybe-java","last_synced_at":"2025-04-13T19:31:59.076Z","repository":{"id":66701975,"uuid":"730986","full_name":"npryce/maybe-java","owner":"npryce","description":"A Maybe type for Java","archived":false,"fork":false,"pushed_at":"2012-12-04T21:35:55.000Z","size":1128,"stargazers_count":69,"open_issues_count":2,"forks_count":18,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-27T10:21:23.469Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://www.growing-object-oriented-software.com","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/npryce.png","metadata":{"files":{"readme":"README","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-06-20T20:29:34.000Z","updated_at":"2024-11-04T09:14:37.000Z","dependencies_parsed_at":"2023-02-20T09:30:53.565Z","dependency_job_id":null,"html_url":"https://github.com/npryce/maybe-java","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/npryce%2Fmaybe-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/npryce%2Fmaybe-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/npryce%2Fmaybe-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/npryce%2Fmaybe-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/npryce","download_url":"https://codeload.github.com/npryce/maybe-java/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248767982,"owners_count":21158567,"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":[],"created_at":"2024-10-15T01:51:59.279Z","updated_at":"2025-04-13T19:31:58.279Z","avatar_url":"https://github.com/npryce.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"The aim of the Maybe type is to avoid using 'null' references.\n\nA Maybe\u003cT\u003e represents a possibly non-existent value of type T.  The Maybe\ntype makes it impossible (without deliberate effort to circumvent the API)\nto use the value when it does not exist.\n\nA Maybe\u003cT\u003e is either unknown(), in which case a known value does not exist,\nor definitely(v), in which case the value is known to be v.\n\nA Maybe\u003cT\u003e is iterable, which means you can use it with the for statement\nto extract a value and do something with it only if there is a value.\n\n   class Customer {\n       public Maybe\u003cString\u003e emailAddress() { ... }\n       ...\n   }\n\n   for (String emailAddress : aCustomer.emailAddress()) {\n       sendEmailTo(emailAddress);\n   }\n\n\nMaybe\u003cT\u003e being iterable really comes into its own when combined with the Guava\n(previously google-collections) library, which has useful functions for\nworking with iterables. You can then work in terms of entire collections\nof things that might or might not exist, without having to test for the existence\nof each one.\n\nFor example, if I have a collection of 'maybe' email addresses, some\nof which might exist and some might not:\n\n    Iterable\u003cMaybe\u003cString\u003e\u003e maybeEmailAddresses = ...\n\nI can get a set of only the actual email addresses in a single expression:\n\n    Set\u003cString\u003e actualEmailAddresses = newHashSet(concat(maybeEmailAddresses));\n\nThe newHashSet and concat functions are defined by Guava.  Concat\ncreates an Iterable\u003cT\u003e from an Iterable\u003cIterable\u003cT\u003e\u003e, concatenating\nthe elements of each sequence into a single sequence.  Because\nunknown() is an empty iterable, the concatenated iterable only returns\nthe definite values.\n\nMore likely, I have an iterable collection of Customers.  Using a\nFunction, I can write a single expression to get the email addresses\nof all customers who have an email address:\n\nHere's a function to map a customer to its 'maybe' email address:\n\n   Function\u003cCustomer,Maybe\u003cString\u003e\u003e toEmailAddress = new Function\u003cCustomer, Maybe\u003cString\u003e\u003e() {\n       public Maybe\u003cString\u003e apply(Customer c) { return c.emailAddress(); }\n   };\n\nAnd here's how to use it to get all the email addresses that my\ncustomers have, so I can send them product announcements:\n\n   Set\u003cString\u003e emailAddresses = newHashSet(\n               concat(transform(customers, toEmailAddress)));\n\nIf I just want to send emails, I don't need the hash set:\n\n   for (String emailAddress : concat(transform(customers, toEmailAddress))) {\n       sendEmailTo(emailAddress);\n   }\n\nThe name \"concat\" is a bit obscure, so I'd probably define an alias\nnamed, for example, \"definite\", to make the code more readable at the\npoint of use.  And the Function definition is a bit clunky, but Java\ndoesn't have (and doesn't look likely to get) a clean syntax for\nreferring to existing functions.\n\nThat's not to say that Maybe doesn't have useful methods to work with\nindividual instances.  For example, the otherwise method:\n\n   T otherwise(T defaultValue);\n\nwill return the Maybe's value if it is known and the defaultValue if it is not.\nE.g.\n\n       assertThat(unknown().otherwise(\"\"), equalTo(\"\"));\n       assertThat(definitely(\"foo\").otherwise(\"\"), equalTo(\"foo\"));\n\nOtherwise is overloaded to take a Maybe\u003cT\u003e as a default:\n\n   Maybe\u003cT\u003e otherwise(Maybe\u003cT\u003e maybeDefaultValue);\n\nwhich lets you chain otherwise expressions:\n\n   assertThat(unknown().otherwise(definitely(\"X\")).otherwise(\"\"), equalTo(\"X\"));\n\nMaybe also has a method that uses a function to map a Maybe\u003cT\u003e to a Maybe\u003cU\u003e\n\n    \u003cU\u003e Maybe\u003cU\u003e to(Function\u003cT,U\u003e mapping);\n\nwhich would transform unknown() to unknown(), otherwise apply the function to\nthe definite value and return the result wrapped in a Maybe.\n\nSimilarly there is a query method that takes a Predicate\u003cT\u003e and maps a Maybe\u003cT\u003e\nto a Maybe\u003cBoolean\u003e.\n\nAll of which API calls make it impossible (without deliberate effort) to try to\nget the value of nothing.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnpryce%2Fmaybe-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnpryce%2Fmaybe-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnpryce%2Fmaybe-java/lists"}