Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Some inline documentation.

  • Loading branch information...
commit a9289fc399c530be867f01e46378c56b37cfe61c 1 parent ef687c3
@mike-burns mike-burns authored
View
26 lib/wrapped/blank.rb
@@ -1,39 +1,65 @@
+# The class represents a lack of something.
class Blank
include Enumerable
+ # It is an error (specifically, an IndexError) to use this method.
def unwrap
raise IndexError.new("Blank has no value")
end
+ # Produce the value that is passed in.
+ #
+ # > w.unwrap_or(0)
def unwrap_or(default)
default
end
+ # Does nothing, returning itself. This is chainable. See blank for its
+ # companion.
+ #
+ # w.present.blank { puts "Missing" }
def present
self
end
+ # Call the block then return itself. This is chainable. See present for its
+ # companion.
+ #
+ # w.blank { puts "I got nothing" }.present {|n| puts "got #{n}" }
def blank(&block)
block.call
self
end
+ # Produce the empty list.
+ #
+ # This class mixes in the Enumerable module, which relies on this.
+ #
+ # > w.each {|n| puts n }
def each
[]
end
+ # False; this is not an instance of a wrapped value.
def present?
false
end
+ # True; this is an instance of nothing.
def blank?
true
end
+ # Do nothing, returning itself.
+ #
+ # > w.try {|n| n+1 }
def try
self
end
+ # Do nothing, returning itself.
+ #
+ # > w.fmap {|n| n+1 }
def fmap
self
end
View
8 lib/wrapped/injection.rb
@@ -2,12 +2,20 @@
require 'wrapped/blank'
class Object
+ # Wrap the object, forcing the user to be aware of the potential for a nil
+ # value by unwrapping it.
+ #
+ # See the Present class for details on how to unwrap it.
def wrapped
Present.new(self)
end
end
class NilClass
+ # Wrap the nil, which is exactly the whole point. At this point the user must
+ # explictly deal with the nil, aware that it exists.
+ #
+ # See the Blank class and the README for details on how to work with this.
def wrapped
Blank.new
end
View
42 lib/wrapped/present.rb
@@ -1,10 +1,19 @@
+# A class that represents a wrapped value. This class holds something that is
+# not nil.
class Present
include Enumerable
- def initialize(value)
+ # Use Object#wrapped and NilClass#wrapped instead.
+ def initialize(value) # :nodoc:
@value = value
end
+ # Produce the value, unwrapped.
+ #
+ # If a block is given apply the block to the value and produce that.
+ #
+ # > w.unwrap_or(0)
+ # > w.unwrap_or("hello") {|s| "Hi, #{s}" }
def unwrap_or(_)
if block_given?
yield unwrap
@@ -13,36 +22,67 @@ def unwrap_or(_)
end
end
+ # Invoke the block on the value, unwrapped. This method produces the wrapped
+ # value again, making it chainable. See `blank' for its companion.
+ #
+ # > w.present {|s| puts "Hello, #{s}" }.blank { puts "Do I know you?" }
def present(&block)
block.call(unwrap)
self
end
+ # Do nothing then produce the wrapped value, making it chainable. See
+ # `present' for its companion.
+ #
+ # > w.blank { puts "Symbol not found" }.present {|s| puts users[s]}
def blank(&ignored)
self
end
+ # Produce the singleton list with the unwrapped value as its only member.
+ #
+ # If a block is passed, it is run against the unwrapped value.
+ #
+ # This class mixes in Enumerable, which is controlled by this method.
+ #
+ # > w.each {|n| puts "Found #{n}" }
def each
yield unwrap if block_given?
[unwrap]
end
+ # The raw value. I doubt you need this method.
def unwrap
@value
end
+ # True; this is an instance of a wrapped value.
def present?
true
end
+ # False; this does not wrap a nil.
def blank?
false
end
+ # Run a block against the unwrapped value, producing the result of the block.
+ #
+ # > w.try {|n| n+1 }
+ #
+ # Also, you can use this like you would use >>= in Haskell. This and wrapped
+ # make it a monad.
+ #
+ # > w.try {|n| (n+1).wrapped }
def try
yield unwrap
end
+ # Run a block within the wrapper. This produces a wrapped value.
+ #
+ # > w.try {|n| n+1 }
+ #
+ # This makes it a functor.
def fmap
(yield unwrap).wrapped
end
Please sign in to comment.
Something went wrong with that request. Please try again.