Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

lab42_result

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lab42_result

  • 0.1.5
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

Gem Version

Lab42::Result

A result encapsulation class, like the Either type in Haskell.

Context Quick Starting Guide

Given


    require "lab42/result/autoimport" # equivalent to: the following lines:
    # require "lab42/result"
    # Result = Lab42::Result

    let(:ok) { Result.ok(42) }
    let(:error) { Result.error("oh no!") }

Accessing a result

If OK

Example: It's ok

  expect( ok ).to be_ok

Example: Its value might be of interest

  expect( ok.value ).to eq(42)

And it will execute the block passed to the if_ok method

    x = nil
    expect(ok.if_ok {x = 42}).to eq(42)
    expect(x).to eq(42)

And the value is passed in

    expect(ok.if_ok{ _1/2}).to eq(21)

But not the one passed to the if_error method

    x = nil
    expect(ok.if_error {x = 42}).to be_nil
    expect(x).to be_nil

Example: And will not raise any error

  expect( ok.raise! ).to eq(42)

And the same holds for raise! with a replacement Exception

  expect( ok.raise!(ArgumentError) ).to eq(42)
If Error

Example: It's h(error)

  expect( error ).not_to be_ok

Example: Its value might (still) be of interest


  expect( error.value ).to eq("oh no!")

Example: And will certainly raise this time

  expect{ error.raise! }.to raise_error(RuntimeError, "oh no!") 

And as often times you will match on an error case only and raise a custom exception the following shortcut comes in handy

  expect{ error.raise!(KeyError) }.to raise_error(KeyError, "oh no!") 

And also you might like to have access to the original message

    expect{ error.raise!(KeyError) { "key not found #{_1}"} }
      .to raise_error(KeyError, "key not found oh no!") 

And it will execute the block passed to the if_error method

    x = nil
    expect(error.if_error {x = 42}).to eq(42)
    expect(x).to eq(42)

And the error and message are passed in

    expect(error.if_error {[_1, _2]}).to eq([RuntimeError, "oh no!"])    

But not the one passed to the if_ok method

    x = nil
    expect(error.if_ok {x = 42}).to be_nil
    expect(x).to be_nil
Capturing Exceptions

If you have a piece of code like this:

    Result.ok(some_computation)
  rescue MyError
    Result.error("Oh my", error: MyError)

you can replace it with the convenient

    Result.from("Oh my") {some_computation}

Given

  def divide by
    Result.from("Zero Division") { 100 / by }
  end

Example: Zero Division, not a problem anymore

  error = divide(0)
  expect( error ).not_to be_ok
  expect( error.status ).to eq(ZeroDivisionError)
    

Example: Correct Division still works

    divide(4) in [_, value]
    expect( value ).to eq(25)

Context A More Detailed View

Ok without a value

Sometimes all we want is an :ok to get back or :error with a message, than we can use the default value of nil

Example: Nil is default for ok

   expect(Result.ok.value).to be_nil
   expect( Result.ok.ok? ).to be_truthy

Error with a different exception

On the other hand you might not want to raise a RuntimeError all the time, that is when the optional keyword parameter error: comes in handy

Example: Error with an Argument

    expect{ Result.error("ooops", error: ArgumentError).raise!}
      .to raise_error(ArgumentError, "ooops")

Context Pattern Matching

Given

    let(:my_error) {Class.new(RuntimeError)}
    let(:message) {"That was bad"}
    let(:surprise) {"Not 42"}
    let(:ok) {Result.ok(surprise)}
    let(:error) {Result.error(message, error: my_error)}

    def match result
      case result
      in [:ok, value]
        value
      in [my_error, message]
        message
      end
    end

Example: Matching The Good

    expect( match(ok) ).to eq(surprise)

Example: Matching The Bad (no, there will be no Ugly)

    expect( match(error) ).to eq(message)

Example: If the Exception I do not want

    error in [_, error_message]
    expect( error_message ).to eq(message)

Context Saveguards

And last but not least, to assure that all instances of Result are frozen we have removed the default constructor (we have not - yet - shadowed Object#allocate though)

Example: Look Mam, no default constructor!

    expect{ Result.new }.to raise_error(NoMethodError)

LICENSE

Copyright 2020 Robert Dober robert.dober@gmail.com

Apache-2.0 c.f LICENSE

FAQs

Package last updated on 04 Dec 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc