{"id":27150935,"url":"https://github.com/havenwood/data-option","last_synced_at":"2025-04-13T19:39:19.431Z","repository":{"id":286664425,"uuid":"962167173","full_name":"havenwood/data-option","owner":"havenwood","description":"Some \u0026 None for Ruby with Rusty semantics","archived":false,"fork":false,"pushed_at":"2025-04-07T19:08:01.000Z","size":11,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-11T16:56:31.288Z","etag":null,"topics":["option","optional","ruby"],"latest_commit_sha":null,"homepage":"https://github.com/havenwood/data-option#readme","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/havenwood.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-04-07T18:47:41.000Z","updated_at":"2025-04-08T02:18:22.000Z","dependencies_parsed_at":"2025-04-07T19:18:21.262Z","dependency_job_id":"37e0f8c2-3aa5-40e5-912b-1b8d3f8d9df5","html_url":"https://github.com/havenwood/data-option","commit_stats":null,"previous_names":["havenwood/data-option"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/havenwood%2Fdata-option","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/havenwood%2Fdata-option/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/havenwood%2Fdata-option/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/havenwood%2Fdata-option/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/havenwood","download_url":"https://codeload.github.com/havenwood/data-option/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248610408,"owners_count":21132920,"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":["option","optional","ruby"],"created_at":"2025-04-08T14:22:34.825Z","updated_at":"2025-04-12T17:54:12.769Z","avatar_url":"https://github.com/havenwood.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Data::Option\n\nThis gem provides a `None` and `Some` with methods for creating, matching, and transforming optional values with Rust-like semantics.\n\n## Installation\n\n```bash\nbundle add data-option\n```\n\nIf you're not using Bundler, install the gem with:\n\n```bash\ngem install data-option\n```\n\n## Usage\n\n### Basic Example\n\nTo use `Some[value]` and `None[]`, first `include Data::Option`.\n\n```ruby\nrequire 'data/option'\n\ninclude Data::Option\n\ndef checked_division(dividend, divisor)\n  if divisor.zero?\n    None[]\n  else\n    Some[dividend / divisor]\n  end\nend\n\ndef try_division(dividend, divisor)\n  case checked_division(dividend, divisor)\n  in None\n    puts \"#{dividend} / #{divisor} failed!\"\n  in Some(quotient)\n    puts \"#{dividend} / #{divisor} = #{quotient}\"\n  end\nend\n\ntry_division(4, 2)\n# \u003e\u003e 4 / 2 = 2\ntry_division(1, 0)\n# \u003e\u003e 1 / 0 failed!\n```\n\n### Creating an Option Value\n\nA `Some` or `None` can be created with multiple syntaxes:\n\n```ruby\nrequire 'data/option'\n\ninclude Data::Option\n\nSome[42]      # =\u003e Some[42]\nNone[]        # =\u003e None\n\nSome.new(42)  # =\u003e Some[42]\nNone.instance # =\u003e None\n```\n\nKernel#Option creates an Option from any value:\n\n```ruby\nrequire 'data/option'\n\nOption(42)       # =\u003e Some[42]\nOption(false)    # =\u003e Some[false]\nOption(nil)      # =\u003e None\n```\n\nThe equivalent class method `Option.from`:\n\n```ruby\nrequire 'data/option'\n\n# Same behavior as the Kernel method\nOption.from(42)    # =\u003e Some[42]\nOption.from(false) # =\u003e Some[false]\nOption.from(nil)   # =\u003e None\n```\n\nEnable Object#to_option via refinements:\n\n```ruby\nrequire 'data/option'\n\nusing Data::Option::Refinement\n\n42.to_option    # =\u003e Some[42]\nfalse.to_option # =\u003e Some[false]\nnil.to_option   # =\u003e None\n\n42.to_option.map(\u0026:succ)   # =\u003e Some[43]\nnil.to_option.map(\u0026:succ)  # =\u003e None\n```\n\n### Predicates\n\nCheck the state of your Option values with predicate methods:\n\n```ruby\nrequire 'data/option'\n\ninclude Data::Option\n\nsome = Some[42]\nnone = None[]\n\nsome.some? # =\u003e true\nsome.none? # =\u003e false\nnone.some? # =\u003e false\nnone.none? # =\u003e true\n\nSome[42].some_and?(\u0026:even?)  # =\u003e true (value exists and is even)\nSome[41].some_and?(\u0026:even?)  # =\u003e false (value exists but isn't even)\nNone[].some_and?(\u0026:even?)    # =\u003e false (no value to check)\n\nSome[42].none_or?(\u0026:even?)   # =\u003e true (either None or predicate is true)\nSome[41].none_or?(\u0026:even?)   # =\u003e false (has value but predicate is false)\nNone[].none_or? { false }    # =\u003e true (None satisfies this predicate)\n```\n\n### Unwrapping\n\nExtract values from an Option safely:\n\n```ruby\nrequire 'data/option'\n\ninclude Data::Option\n\nsome = Some[42]\nnone = None[]\n\nsome.unwrap  # =\u003e 42\nnone.unwrap  #!\u003e None::UnwrapError\n\nsome.unwrap_or(0)  # =\u003e 42\nnone.unwrap_or(0)  # =\u003e 0\n\nsome.unwrap_or_else { rand(100) }  # =\u003e 42\nnone.unwrap_or_else { rand(100) }  # =\u003e some random number\n\nsome.expect('Should contain value')  # =\u003e 42\nnone.expect('Missing expected value')  #!\u003e None::UnwrapError\n```\n\n### Enumeration and Transformation\n\nMap, filter, and transform Option values:\n\n```ruby\nrequire 'data/option'\n\ninclude Data::Option\n\nSome[42].each { |value| puts value }  # prints 42\nNone[].each { |value| puts value }    # no output\n\nSome[42].map { |n| n + 1 }  # =\u003e Some[43]\nNone[].map { |n| n + 1 }    # =\u003e None\n\nSome[42].filter(\u0026:even?)    # =\u003e Some[42]\nSome[41].filter(\u0026:even?)    # =\u003e None\nNone[].filter { true }      # =\u003e None\n\nSome[42].flat_map { |n| Some[n + 1] }  # =\u003e Some[43]\nSome[42].flat_map { |_| None[] }       # =\u003e None\nNone[].flat_map { |n| Some[n + 1] }    # =\u003e None\n\nSome[Some[42]].flatten  # =\u003e Some[42]\nSome[None[]].flatten    # =\u003e None\nSome[42].flatten        # =\u003e Some[42]\nNone[].flatten          # =\u003e None\n\nSome[42].map_or(0) { |n| n + 1 }  # =\u003e 43\nNone[].map_or(0) { |n| n + 1 }    # =\u003e 0\n\nSome[42].map_or_else(-\u003e { rand(100) }) { |n| n + 1 }  # =\u003e 43\nNone[].map_or_else(-\u003e { rand(100) }) { |n| n + 1 }    # =\u003e random number\n```\n\n### Logical Operations\n\nCombine Option values with logical operations:\n\n```ruby\nrequire 'data/option'\n\ninclude Data::Option\n\nSome[1].and(Some[2])  # =\u003e Some[2]\nSome[1].and(None[])   # =\u003e None\nNone[].and(Some[1])   # =\u003e None\nNone[].and(None[])    # =\u003e None\n\nSome[1].and_then { |n| Some[n + 1] }  # =\u003e Some[2]\nSome[1].and_then { |_| None[] }       # =\u003e None\nNone[].and_then { |n| Some[n + 1] }   # =\u003e None\n\nSome[1].or(Some[2])  # =\u003e Some[1]\nSome[1].or(None[])   # =\u003e Some[1]\nNone[].or(Some[2])   # =\u003e Some[2]\nNone[].or(None[])    # =\u003e None\n\nSome[1].or_else { Some[2] }  # =\u003e Some[1]\nNone[].or_else { Some[2] }   # =\u003e Some[2]\nNone[].or_else { None[] }    # =\u003e None\n\nSome[1].xor(Some[2])  # =\u003e None\nSome[1].xor(None[])   # =\u003e Some[1]\nNone[].xor(Some[2])   # =\u003e Some[2]\nNone[].xor(None[])    # =\u003e None\n```\n\n### String Representation and Formatting\n\nOptions provide clear string representations:\n\n```ruby\nrequire 'data/option'\n\ninclude Data::Option\n\nSome[42].to_s     # =\u003e \"Some[42]\"\nSome[42].inspect  # =\u003e \"Some[42]\"\nNone[].to_s       # =\u003e \"None\"\nNone[].inspect    # =\u003e \"None\"\n\nSome[[1, 2, 3]].inspect         # =\u003e \"Some[[1, 2, 3]]\"\nSome[Some[\"hello\"]].inspect     # =\u003e \"Some[Some[\\\"hello\\\"]]\"\n\nrequire 'pp'\nPP.pp(Some[42])             # Some[ 42 ]\nPP.pp(Some[Some[None[]]])   # Some[ Some[ None ] ]\n```\n\n### Comparison and Sorting\n\n`Some` and `None` are comparable and sortable. `None` is considered lower than all `Some` values, and `Some` values are ordered by their contained values:\n\n```ruby\nrequire 'data/option'\n\ninclude Data::Option\n\nSome[1] \u003c Some[2]  # =\u003e true\nSome[2] \u003e Some[1]  # =\u003e true\nSome[1] == Some[1] # =\u003e true\n\nSome[1] \u003e None[]   # =\u003e true\nNone[] \u003c Some[1]   # =\u003e true\n\n[Some[3], None[], Some[1], Some[2]].sort  # =\u003e [None[], Some[1], Some[2], Some[3]]\n```\n\n### Method Chaining\n\nChain operations for elegant functional transformations:\n\n```ruby\nrequire 'data/option'\n\ninclude Data::Option\n\nOption(42)\n  .map { |it| it * 10 }               # =\u003e Some[420]\n  .flat_map { |it| Option(it - 440) } # =\u003e Some[-20]\n  .filter(\u0026:positive?)                # =\u003e None\n  .map { |it| it * 10 }               # =\u003e None\n  .unwrap_or(99)                      # =\u003e 99\n```\n\n### Method Overview\n\n`Some` and `None` both respond to a wide range of utility methods that cover common functional programming patterns:\n\n- Checking: `some?`, `none?`, `some_and?`, `none_or?`\n- Unwrapping: `unwrap`, `unwrap_or`, `unwrap_or_else`, `expect`\n- Transforming: `map`, `flat_map`, `filter`, `flatten`, `map_or`, `map_or_else`, `each`\n- Combining: `and`, `and_then`, `or`, `or_else`, `xor`\n- Formatting: `to_s`, `inspect`\n- Comparison: `\u003c=\u003e`, `==`, `\u003c`, `\u003e`, etc.\n\nSee Rust's Option [Method overview](https://doc.rust-lang.org/std/option/#method-overview) for background and inspiration for these methods.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhavenwood%2Fdata-option","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhavenwood%2Fdata-option","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhavenwood%2Fdata-option/lists"}