Class: Maybe

Inherits:
Object show all
Defined in:
lib/maybe.rb

Constant Summary collapse

LEGACY_METHODS =
%w{value pass fmap join}

Instance Method Summary collapse

Constructor Details

#initialize(value) ⇒ Maybe

Initializes a new Maybe object

Parameters:

  • value

    Any Ruby object (nil or non-nil)



13
14
15
16
# File 'lib/maybe.rb', line 13

def initialize(value)
  @value = value
  __join__
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/maybe.rb', line 32

def method_missing(method_name, *args, &block)
  if LEGACY_METHODS.include?(method_name.to_s)
    if @value.respond_to?(method_name)
      @value.send(method_name, *args, &block)
    else
      __send__("__#{method_name}__", *args, &block)
    end
  else
    __fmap__ do |value|
      value.send(method_name,*args) do |*block_args|
        yield(*block_args) if block_given?
      end
    end
  end
end

Instance Method Details

#__fmap__Object

Only included to provide a complete Monad interface. Not recommended for general use. (Technically: Given that the value is of type A takes a function from A->B and returns M (a monad with a value of type B))



78
79
80
81
82
83
84
# File 'lib/maybe.rb', line 78

def __fmap__
  if(@value==nil)
    self
  else
    Maybe.new(yield(@value))
  end
end

#__join__Object

Only included to provide a complete Monad interface. Not recommended for general use. (Technically: M[M] is equivalent to M, that is, monads should be flat rather than nested)



90
91
92
93
94
95
# File 'lib/maybe.rb', line 90

def __join__
  if(@value.is_a?(Maybe))
    @value = @value.__value__
  end
  self
end

#__pass__Object

Only included to provide a complete Monad interface. Not recommended for general use. (Technically: Given that the value is of type A takes a function from A->M and returns M (a monad with a value of type B))



69
70
71
# File 'lib/maybe.rb', line 69

def __pass__
  __fmap__ {|*block_args| yield(*block_args)}.__join__
end

#__value__(value_if_nil = nil) ⇒ Object

Unwraps the Maybe object. If the wrapped object does not define #value you may call #value instead of _value_

Parameters:

  • value_if_nil (defaults to: nil)

    A value to return if the wrapped value is nil.

Returns:

  • the wrapped object



52
53
54
55
56
57
58
# File 'lib/maybe.rb', line 52

def __value__(value_if_nil=nil)
  if(@value==nil)
    value_if_nil
  else
    @value
  end
end

#methodsObject



23
24
25
# File 'lib/maybe.rb', line 23

def methods
  super + @value.methods + LEGACY_METHODS
end

#nil?Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/maybe.rb', line 60

def nil?
  @value==nil
end

#respond_to?(method_name) ⇒ Boolean

Returns:

  • (Boolean)


18
19
20
21
# File 'lib/maybe.rb', line 18

def respond_to?(method_name)
  return true if LEGACY_METHODS.include?(method_name.to_s)
  super || @value.respond_to?(method_name)
end

#respond_to_missing?(method_name, *args, &block) ⇒ Boolean

Returns:

  • (Boolean)


27
28
29
30
# File 'lib/maybe.rb', line 27

def respond_to_missing?(method_name, *args, &block)
  # For Ruby 1.9 support
  super
end