result

Result

The Result type, but for Crystal!

Installation

  1. Add the dependency to your shard.yml:
dependencies:
  result:
    codeberg: elliethepuppy/result
    version: 1.0.0
  1. Run shards install

Usage

require "result"
  • NOTE: this will also include the Result(T, E), Ok(T), and Err(T) types directly into your top-level scope. if you wish to avoid this, require like so:
    require "result/result"
    

A Result type signature looks like Result(T, E), where T is the type of your good value and E is the type of your error value. It is recommended to always use different types if you are not creating your own Ok and Err objects to give to the Result because the constructors can become confused.

alias ExampleResult = Result(Int32, String)
# using some given value to initialize
good_result = ExampleResult.new 5 + 3     # => Ok(8)
bad_result  = ExampleResult.new "bad val" # => Err("bad val")

Using a given Ok or Err value, created with the corresponding macro

good_result = ExampleResult.new(ok(2 * 43)) # => Ok(86)
bad_result  = ExampleResult.new(err("huh")) # => Err("huh")

Using a Block to determine a value or error value to initialize.

good_or_bad_result = Result(Float64, String).new do
  random = rand(-10..10)
  if random == 0
    "nooooo!"
  else
    4 / random
  end # => Ok(<Some Float64>) or Err("nooooo!")
end

Similar to the above, a Proc can be used (and is in fact how the block variant is implemented) instead of a Block.

four_six_seven = -> { if rand(0..1) % 2 == 0; 467; else; "467" }
good_or_bad_result = ExampleResult.new four_six_seven # => Ok(467) or Err("467")

Check if a value is good or bad with #ok? and #err?.

good_result = ExampleResult.new(ok(87)) # => Ok(87)
good_result.ok?                         # => true
good_result.err?                        # => false

Trying to unwrap a non-Ok value raises a ResultType::ResultError.

good_result = ExampleResult.new(ok(9300)).unwrap # => Ok(9300), Looks great!
bad_result  = ExampleResult.new(err("l")).unwrap # => raises ResultType::ResultError!! Ick!!!

Of course, if you must unwrap the contained value, whether it is or isn't good, use #unwrap!.

suspect_result = ExampleResult.new(err("dangerous!")).unwrap! # => Err("dangerous!"), scary!!

You can also deliberately unwrap an error using #unwrap_err. This has the same rules as regular #unwrap, except for error values.

bad_result = ExampleResult.new(err("expected!")).unwrap_err # => Err("expected!"), not scary!!

In addition to #unwrap and #unwrap_err are #expect(message) and #expect_err(message). These latter two methods function identically to the former two, except the exception message given on failure is the one you provide to the method. You must provide the message.

good_result = ExampleResult.new(err("string"))
              .expect("Should be Int32")      # => raises `ResultType::ResultError` with "Should be Int32".
bad_result  = ExampleResult.new(ok(75))
              .expect_err("Should be String") # => raises `ResultType::ResultError` with "Should be String".

Development

TODO:

  • Determine if having Ok(T), Err(E), and Result(T, E) being completely separate types is ideal.
  • Write tests for: Comparables, Ok(T), and Err(E).
    • Do Ok(T) and Err(E) really need tests? they're quite simple, and are tested by being so tied to the Result type itself.

Contributing

  1. Clone it (git clone https://codeberg.org/elliethepuppy/result.git)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Create a patch against the main branch (git diff main > feature-name.patch)
  5. Send me an email whose subject begins with [GIT/Result] (Include your feature name as well!). If you don't, I might not get it.
  6. Wait for me to get back to you with questions and updates!

Contributors

Repository

result

Owner
Statistic
  • 0
  • 0
  • 0
  • 0
  • 0
  • about 8 hours ago
  • June 21, 2026
License

MIT License

Links
Synced at

Sun, 21 Jun 2026 03:39:44 GMT

Languages