{"id":15062331,"url":"https://github.com/paudirac/error-rop","last_synced_at":"2025-07-12T19:30:54.121Z","repository":{"id":56832017,"uuid":"91826426","full_name":"paudirac/Error-ROP","owner":"paudirac","description":"Perl either","archived":false,"fork":false,"pushed_at":"2017-10-13T16:19:22.000Z","size":51,"stargazers_count":2,"open_issues_count":3,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-22T02:50:22.844Z","etag":null,"topics":["either","functional-programming","perl5"],"latest_commit_sha":null,"homepage":null,"language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paudirac.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-19T16:44:23.000Z","updated_at":"2017-08-08T07:39:58.000Z","dependencies_parsed_at":"2022-09-08T05:10:29.758Z","dependency_job_id":null,"html_url":"https://github.com/paudirac/Error-ROP","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/paudirac%2FError-ROP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paudirac%2FError-ROP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paudirac%2FError-ROP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paudirac%2FError-ROP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paudirac","download_url":"https://codeload.github.com/paudirac/Error-ROP/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225834404,"owners_count":17531469,"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":["either","functional-programming","perl5"],"created_at":"2024-09-24T23:34:33.801Z","updated_at":"2024-11-22T02:50:29.743Z","avatar_url":"https://github.com/paudirac.png","language":"Perl","readme":"# NAME\n\nError::ROP - A simple and lightweight implementation error handling library for Perl,\ninspired in the Rop type.\n\n# SYNOPSIS\n\n    use Error::ROP qw(rop);\n\n    my $meaning =  rop { 80 / $divisor }-\u003ethen(sub { $_ + 2 });\n\n    say \"The life meaning is \" . $meaning-\u003evalue if $meaning-\u003eis_valid;\n    warn \"Life has no meaning\" if not $meaning-\u003eis_valid;\n\n# DESCRIPTION\n\nThe purpose of the `rop` function is to let you focus in the happy path\nand provide a nice way to treat failures without filling the code\nwith `eval`s and `if`s that always serve almost the same purpose.\n\nSupose you have a computation that can fail depending on some condition.\nFor the sake of simplicity consider the following code\n\n    sub compute_meaning {\n        my $divisor = shift;\n        return 2 + 80 / $divisor;\n    };\n\nthat will fail when called with a zero argument.\n\nFollowing the style of the [Railway Oriented Programming](https://fsharpforfunandprofit.com/rop/), you wrap the part\nthat could fail in a `rop` block and focus on programming the happy\npath:\n\n    sub compute_meaning {\n        my $divisor = shift;\n        return rop { 80 / $divisor }\n               -\u003ethen(sub { $_ + 2 });\n    };\n\nThis way, the `compute_meaning` function will never blow, even when\npassed in a zero argument and the computation doesn't make sense. The caller\ncan check that the computation succeeded by asking the `rop` result\nobject.\n\nWhen the computation succeeds, the `value` property contains\nthe computation result\n\n    my $meaning = compute_meaning(2);\n    say \"The life meaning is \" $meaning-\u003evalue if $meaning-\u003eis_valid;\n\nand when the computation fails, you can also inform the user or decide how to\nproceed, by inspecting the `failure` value, which will contain the captured\nerror.\n\n    my $meaning = compute_meaning(0);\n    warn \"Life has no meaning: \" . $meaning-\u003efailure if not $meaning-\u003eis_valid;\n\n## Chaining\n\nThe real usability gain of using `rop` occurs when you have a recipe\nthat comprises several things to do and you need to stop at the first step\nthat fails.\n\nThat is, you need to chain or compose several functions that\nin the happy path would be executed one after another but in the real path, you\nwould have to check for any of them if had failed or not and proceed with\nthe next or stop and report the errors.\n\nWith `rop` you can leverage the checking to the library and just program\nthe happy path functions and chain them with the `then` method:\n\n    use Error::ROP;\n\n    my $res = rop { 40 / $something }\n      -\u003ethen(sub { $_ / 2 })\n      -\u003ethen(sub { $_ * 4 })\n      -\u003ethen(sub { $_ + 2 });\n\nYou can always know if the computation has succed by inspecting the rop,\n\n    say $res-\u003evalue if $res-\u003eis_valid;\n\nor treat the error otherwise\n\n    warn $res-\u003efailure if not $res-\u003eis_valid;\n\nThe computation will short-circuit and return with the first error occurred,\nno matter how many chained functions remain after the failing step.\n\n## On Either types and then\n\nThis module does not implement the Either type in Perl. The Haskell, F#, ML and\nother strongly typed functional programming languages have Either types. This\nis not a generic type like Haskell's `Either a b`.\n\nOn those PL you have a strong type system and generic programming facilities that\nallow you to generalize operations into higher abstractions. In particular, you\ncan operate in elevated (monadic) types as if they where first class values and the\nlanguages provide tools (generic functions and operators) that allow you to\ncompose those operations by somehow overloading composition.\n\nWhen adopting an Either type to implement ROP in those languages, you normally use\nthe ` \u003e=\u003e ` operator to overload composition. Actually, you use it to compose\nfunctions of the type\n\n    \u003e=\u003e :: (a -\u003e Either b e) -\u003e (b -\u003e Either c e) -\u003e (a -\u003e Either c e)\n\nThis library just uses a wrapper object (the Error::ROP instance) that has a method `then` to somehow\ncompose other operations. This is a much less flexible approach but it works and is easy to understand.\nThe two leaves of the type are accessible via the instance's `value` and `failure` getters.\n\nThe only confusion might be that it ressembles the `then` function of a promise or future. This is not\nexactly the same. Just keep that in mind.\n\n## USAGE\n\nYou can find more usage examples in the tests `t/Then.t`. For examples of\nhow to use inside Moose `t/Example.t`\n\n## Running tests\n\nA `Dockerfile` is provided in order to run the tests without needing\nany perl in your system. Just run:\n\n    $ make -f Makefile.docker test\n\nThis should construct an image with the necessary dependencies, copy\nthe source into the image and run the tests.\n\n# AUTHOR\n\n[Pau Cervera i Badia](https://metacpan.org/pod/pau.cervera@capside.com)\n\nCAPSiDE\n\n# BUGS and SOURCE\n\nThe source code is located here: [https://github.com/paudirac/Error-ROP](https://github.com/paudirac/Error-ROP)\n\nPlease report bugs to: [https://github.com/paudirac/Error-ROP/issues](https://github.com/paudirac/Error-ROP/issues)\n\n# COPYRIGHT and LICENSE\n\nCopyright (c) 2017 by CAPSiDE\n\nThis code is distributed under the Apache 2 License. The full text of the license can be found in the LICENSE file included with this module.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaudirac%2Ferror-rop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaudirac%2Ferror-rop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaudirac%2Ferror-rop/lists"}