Skip to content

v1.2.0

Compare
Choose a tag to compare
@bolshakov bolshakov released this 15 Nov 21:52
· 79 commits to master since this release
512d95c

Fear::Future#zip

Now you can call Future#zip with block argument which maps result

this = Fear.future { 1 }
that = Fear.future { 2 }
this.zip(that) { |x, y| x + y } #=> Fear.success(3)

Fear::Option#zip

Fear.some("foo").zip(Fear.some("bar")) #=> Fear.some(["foo", "bar"])
Fear.some("foo").zip(Fear.some("bar")) { |x, y| x + y } #=> Fear.some("foobar")
Fear.some("foo").zip(Fear.none) #=> Fear.none
Fear.none.zip(Fear.some("bar")) #=> Fear.none

Fear::Option#filter_map

Returns a new Some of truthy results (everything except false or nil) or +None+ otherwise.

Fear.some(42).filter_map { |v| v/2 if v.even? } #=> Fear.some(21)
Fear.some(42).filter_map { |v| v/2 if v.odd? } #=> Fear.none
Fear.some(42).filter_map { |v| false } #=> Fear.none
Fear.none.filter_map { |v| v/2 }   #=> Fear.none

Dry-Types and Dry-Struct integration

require 'dry-types'
require 'dry/types/fear'

Dry::Types.load_extensions(:fear_option)

module Types
  include Dry.Types()
end

Append .option to a type name to return Fear::Option of object:

Types::Option::Strict::Integer[nil] 
#=> Fear.none
Types::Option::Coercible::String[nil] 
#=> Fear.none
Types::Option::Strict::Integer[123] 
#=> Fear.some(123)
Types::Option::Strict::String[123]
#=> Fear.some(123)
Types::Option::Coercible::Float['12.3'] 
#=> Fear.some(12.3)

Option types can also accessed by calling .option on a regular type:

Types::Strict::Integer.option # equivalent to Types::Option::Strict::Integer

You can define your own optional types:

option_string = Types::Strict::String.option
option_string[nil]
# => Fear.none
option_string[nil].map(&:upcase)
# => Fear.none
option_string['something']
# => Fear.some('something')
option_string['something'].map(&:upcase)
# => Fear.some('SOMETHING')
option_string['something'].map(&:upcase).get_or_else { 'NOTHING' }
# => "SOMETHING"

You can use it with dry-struct as well:

class User < Dry::Struct
  attribute :name, Types::Coercible::String
  attribute :age,  Types::Coercible::Integer.option
end

user = User.new(name: 'Bob', age: nil)
user.name #=> "Bob"
user.age #=> Fear.none 

user = User.new(name: 'Bob', age: 42)
user.age #=> Fear.some(42) 

Implement pattern matching for ruby >= 2.7

Pattern matching works for Fear::Option, Fear::Either, and Fear::Try:

case Fear.some(41)
in Fear::Some(x) if x.even?
  x / 2
in Fear::Some(x) if x.odd? && x > 0
  x * 2
in Fear::None
  'none'
end #=> 82

Fear.xcase is deprecated and will be removed in fear 2.0.