rfunc 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Guardfile +25 -0
- data/LICENSE.txt +22 -0
- data/README.md +124 -0
- data/Rakefile +1 -0
- data/lib/rfunc.rb +17 -0
- data/lib/rfunc/errors.rb +9 -0
- data/lib/rfunc/option.rb +334 -0
- data/lib/rfunc/seq.rb +181 -0
- data/lib/rfunc/version.rb +3 -0
- data/rfunc.gemspec +26 -0
- data/spec/rfunc/option_spec.rb +243 -0
- data/spec/rfunc/seq_spec.rb +441 -0
- data/spec/rfunc_spec.rb +29 -0
- data/spec/spec_helper.rb +19 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5ada99d6bda2552bc00c7b03da343402a02c8eb6
|
4
|
+
data.tar.gz: c5ca325b37d69b6ce07f5f559d0d6689c1c91f5a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5f791b958bc7def9f8657c9e200037298f190f5d4886f7755813450b487e3521948ead4be2620bacefc64af27fb7508e1750c472e338819f7a18faeca0343528
|
7
|
+
data.tar.gz: 3ee8bca64120fb8ea66c742e3bd12859ce069784ff6c3967dcad97984e74f32f57cb94d7d9a0a161bc2635fe1a2a6a9ef5d42878a3de9a1e43095a2798e5f4a8
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rfunc
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.2
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :rspec, :cmd => 'bundle exec rspec' do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
8
|
+
watch('spec/spec_helper.rb') { "spec" }
|
9
|
+
|
10
|
+
# Rails example
|
11
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
12
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
13
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
14
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
15
|
+
watch('config/routes.rb') { "spec/routing" }
|
16
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
17
|
+
|
18
|
+
# Capybara features specs
|
19
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
20
|
+
|
21
|
+
# Turnip features and steps
|
22
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
23
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
24
|
+
end
|
25
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Paul De Goes
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# RFunc
|
2
|
+
|
3
|
+
This gem provides access to a functionally oriented collections library. First release will include Seq and Option support.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'rfunc'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle install
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rfunc
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
###RFunc
|
22
|
+
The RFunc module provides access to some helper methods that let you form RFunc classes in a less verbosity.
|
23
|
+
|
24
|
+
require "rfunc"
|
25
|
+
|
26
|
+
include RFunc
|
27
|
+
|
28
|
+
Seq([1,2,3]) => RFunc::Seq(1,2,3)
|
29
|
+
|
30
|
+
Option(nil) => RFunc::None
|
31
|
+
|
32
|
+
Option(1) => RFunc::Some(1)
|
33
|
+
|
34
|
+
|
35
|
+
####RFunc::Seq
|
36
|
+
The RFunc::Seq (Sequence) is a replacement for the Ruby Array class which it accepts and provides the following methods:
|
37
|
+
|
38
|
+
* [] => access an element of the Seq by index
|
39
|
+
|
40
|
+
RFunc::Seq.new([1])[0] => 1
|
41
|
+
|
42
|
+
* head => return the first element of the Seq
|
43
|
+
|
44
|
+
RFunc::Seq.new([1]).head => 1
|
45
|
+
|
46
|
+
* head_option => return an Option of the first element of the Seq
|
47
|
+
|
48
|
+
RFunc::Seq.new([1]).head_option => Some(1)
|
49
|
+
|
50
|
+
* tail => return all elements of the Seq except the head
|
51
|
+
|
52
|
+
RFunc::Seq.new([1,2,3]).tail => Seq([2,3])
|
53
|
+
|
54
|
+
* tail_option => return an Option of all the elements of the Seq
|
55
|
+
|
56
|
+
RFunc::Seq.new([1,2,3]).tail_option => Some(Seq([2,3]))
|
57
|
+
|
58
|
+
* map(block) => returns a Seq, the members of which have been operated on by the provided block
|
59
|
+
|
60
|
+
RFunc::Seq.new([1,2,3]).map{|v| v*2 } => Seq([2, 4, 6])
|
61
|
+
|
62
|
+
* slice(from, to) => returns a Seq containing the given range
|
63
|
+
|
64
|
+
RFunc::Seq.new([1,2,3,4,5]).slice(2,3) => Seq([2,3,4])
|
65
|
+
|
66
|
+
* fold(accum, &block) => returns the value of the yielded block, which takes an accumulator and a Seq element from left to right
|
67
|
+
|
68
|
+
RFunc::Seq.new([1,2,3]).fold(RFunc::Seq.new([])) {|accum, el| accum.append(el + el) } => Seq([2,4,6])
|
69
|
+
|
70
|
+
* foldr(accum, &block) => returns the value of the yielded block, which takes an accumulator and a Seq element from right to left
|
71
|
+
|
72
|
+
RFunc::Seq.new([1,2,3]).foldr(RFunc::Seq.new([])) {|accum, el| accum.append(el + el) } => Seq([6,4,2])
|
73
|
+
|
74
|
+
* first_option => returns an Option of the first element (Some of None)
|
75
|
+
|
76
|
+
RFunc::Seq.new([1,2]).first_option => Some(1)
|
77
|
+
RFunc::Seq.new([]).first_option => None
|
78
|
+
|
79
|
+
* last_option => returns an Option of the last element (Some of None)
|
80
|
+
|
81
|
+
RFunc::Seq.new([1,2]).last_option => Some(2)
|
82
|
+
RFunc::Seq.new([]).last_option => None
|
83
|
+
|
84
|
+
* append(el) => returns an RFunc::Seq with the element appended
|
85
|
+
|
86
|
+
RFunc::Seq.new([1]).append(2) => Seq([1,2])
|
87
|
+
|
88
|
+
* prepend(el) => returns an RFunc::Seq with the element prepended
|
89
|
+
|
90
|
+
RFunc::Seq.new([2]).prepend(1) => Seq([1,2])
|
91
|
+
|
92
|
+
* empty? => returns true or false based on whether or not there are elements in the Seq
|
93
|
+
|
94
|
+
RFunc::Seq.new([]).empty? => true
|
95
|
+
RFunc::Seq.new([1]).empty? => false
|
96
|
+
|
97
|
+
* reverse => returns an RFunc::Seq with the elements reversed
|
98
|
+
|
99
|
+
RFunc::Seq.new([1,2,3,4,5]).reverse => Seq([5,4,3,2,1])
|
100
|
+
|
101
|
+
* concat => returns an RFunc::Seq with the provided elements appended
|
102
|
+
RFunc::Seq.new([1,2,3]).concat([2,1]) => Seq([1, 2, 3, 2, 1])
|
103
|
+
RFunc::Seq.new([1,2,3]).concat(RFunc::Seq.new([2,1])) => Seq([1, 2, 3, 2, 1])
|
104
|
+
|
105
|
+
* flat_map => returns a flattened RFunc::Seq, whose members are derived from operating on each element of the existing Seq
|
106
|
+
RFunc::Seq.new([1,2,3]).flat_map {|el| [el, el -1, el -2] } => Seq([1, 0, -1, 2, 1, 0, 3, 2, 1]>)
|
107
|
+
|
108
|
+
## CAVEATES
|
109
|
+
|
110
|
+
Ruby is NOT a functional language, nor is it optimized for functional code (tail call recursion for instance). As a result, this library utilizes native Ruby comprehensions in order to remain performant and useful. Any libraries built on this code should take the same approach.
|
111
|
+
|
112
|
+
## TODO
|
113
|
+
|
114
|
+
* Complete Seq library
|
115
|
+
* Complete Option library
|
116
|
+
* head
|
117
|
+
|
118
|
+
## Contributing
|
119
|
+
|
120
|
+
1. Fork it ( http://github.com/<my-github-username>/rfunc/fork )
|
121
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
122
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
123
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
124
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/rfunc.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rfunc/version"
|
2
|
+
require "rfunc/option"
|
3
|
+
require "rfunc/seq"
|
4
|
+
require "rfunc/errors"
|
5
|
+
|
6
|
+
|
7
|
+
module RFunc
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def Seq(a); RFunc::Seq.new(a) end
|
11
|
+
|
12
|
+
def Option(v); RFunc::Option.new(v) end
|
13
|
+
|
14
|
+
def Some(v); RFunc::Some.new(v) end
|
15
|
+
|
16
|
+
def None; RFunc::None.new end
|
17
|
+
end
|
data/lib/rfunc/errors.rb
ADDED
data/lib/rfunc/option.rb
ADDED
@@ -0,0 +1,334 @@
|
|
1
|
+
require 'rfunc/errors'
|
2
|
+
|
3
|
+
module RFunc
|
4
|
+
class AbstractOption
|
5
|
+
# Initializes the class
|
6
|
+
#
|
7
|
+
# @param value [Any] the initial value of the Option
|
8
|
+
#
|
9
|
+
# @return [AbstractOption] and instance of the class
|
10
|
+
#
|
11
|
+
def initialize(value)
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
# Comparator that allows one Option to be compared against another
|
16
|
+
# by value
|
17
|
+
#
|
18
|
+
# @return [Boolean] true if the Option values are identical and false
|
19
|
+
# if not
|
20
|
+
#
|
21
|
+
def ==(object)
|
22
|
+
object.class == self.class && object.get == @value
|
23
|
+
end
|
24
|
+
|
25
|
+
# Extracts the value of the option
|
26
|
+
#
|
27
|
+
# @return [Any] the value of the option
|
28
|
+
def get; @value end
|
29
|
+
|
30
|
+
# Filters the Some by a given function
|
31
|
+
#
|
32
|
+
# @param block [Function] the function which will operate on the
|
33
|
+
# option's value if present (should return Bool) and
|
34
|
+
# be used to determine if a Some of None will be
|
35
|
+
# returned
|
36
|
+
# @return [RFunc::Option] the Option result of the filter
|
37
|
+
#
|
38
|
+
def filter(&block)
|
39
|
+
map {|el| yield(el)}.get_or_else { false } ? self : None.new
|
40
|
+
end
|
41
|
+
|
42
|
+
# Filters the Some by the inverse of a given function
|
43
|
+
#
|
44
|
+
# @param block [Function] the function which will operate on the
|
45
|
+
# option's value if present (should return Bool) and
|
46
|
+
# be used to determine if a Some of None will be
|
47
|
+
# returned
|
48
|
+
# @return [RFunc::Option] the Option result of the filter
|
49
|
+
#
|
50
|
+
def filter_not(&block)
|
51
|
+
map {|el| !yield(el) }.get_or_else { false } ? self : None.new
|
52
|
+
end
|
53
|
+
|
54
|
+
alias_method :find, :filter
|
55
|
+
|
56
|
+
# Tests whether or not an object is an Option
|
57
|
+
#
|
58
|
+
# @param el [Any] the object to test
|
59
|
+
#
|
60
|
+
# @return [Boolean] true if the object is an Option or false if not
|
61
|
+
#
|
62
|
+
def is_option?(el)
|
63
|
+
el.is_a?(AbstractOption)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def validated_option_type(r)
|
69
|
+
raise RFunc::Errors::InvalidReturnType.new(r, AbstractOption) if !is_option?(r)
|
70
|
+
r
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Some < AbstractOption
|
75
|
+
def initialize(something)
|
76
|
+
throw "RFunc::Some cannot be initialized with a nil" if something.nil?
|
77
|
+
super(something)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Maintains signiture parity with None.get_or_else
|
81
|
+
#
|
82
|
+
# @param block [Function] the value that would return if the current
|
83
|
+
# Option was a None
|
84
|
+
#
|
85
|
+
# @return [Any] Option value
|
86
|
+
#
|
87
|
+
def get_or_else(&block)
|
88
|
+
get
|
89
|
+
end
|
90
|
+
|
91
|
+
# Maintains signiture parity with None.or_else
|
92
|
+
#
|
93
|
+
# @param v [Option] the option that would return if the present Option
|
94
|
+
# were a None
|
95
|
+
#
|
96
|
+
# @return [Option] the current option
|
97
|
+
#
|
98
|
+
def or_else(v)
|
99
|
+
self
|
100
|
+
end
|
101
|
+
|
102
|
+
# Operates on the Option value
|
103
|
+
#
|
104
|
+
# @param block [Function] the function which will be used to operate
|
105
|
+
# on the Option's value
|
106
|
+
#
|
107
|
+
# @return [Option] the result of the function's operation
|
108
|
+
# as an Option
|
109
|
+
#
|
110
|
+
def map(&block)
|
111
|
+
Option.new(yield(@value))
|
112
|
+
end
|
113
|
+
|
114
|
+
# Indicates if the Option has a value
|
115
|
+
#
|
116
|
+
# @return [Boolean] false
|
117
|
+
#
|
118
|
+
def empty?
|
119
|
+
false
|
120
|
+
end
|
121
|
+
|
122
|
+
# Applies a function to the value of the Option and
|
123
|
+
# flattens the resulting Option[Option] into a single Option
|
124
|
+
#
|
125
|
+
# @param block [Function] the function which will operate on the
|
126
|
+
# Option's value (should return an Option)
|
127
|
+
#
|
128
|
+
# @return [RFunc::Option] the Option result of flattening the current
|
129
|
+
# provided function's option
|
130
|
+
#
|
131
|
+
def flat_map(&block)
|
132
|
+
validated_option_type(yield(get))
|
133
|
+
end
|
134
|
+
|
135
|
+
# Operates on the value of the Option
|
136
|
+
#
|
137
|
+
# @param alternate [Any] the value to return if the Option is a None
|
138
|
+
# @param block [Function] the function which will operate on the
|
139
|
+
# current Option's value
|
140
|
+
#
|
141
|
+
# @return [Any] the result of applying the supplied block to the current
|
142
|
+
# Option value
|
143
|
+
#
|
144
|
+
def fold(alternate, &block)
|
145
|
+
yield(get)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Flattens nested Options into a single option
|
149
|
+
#
|
150
|
+
# @return [Option] a Some if the contained value is a Some or a None
|
151
|
+
# if not
|
152
|
+
#
|
153
|
+
def flatten
|
154
|
+
is_option?(@value) ? @value : self
|
155
|
+
end
|
156
|
+
|
157
|
+
# Operates on the value of the Option if it exists and meets a criteria
|
158
|
+
#
|
159
|
+
# @param block [Function] the block that can be used to modify the value
|
160
|
+
# (should be a case statement with nil return for non operation)
|
161
|
+
#
|
162
|
+
# @return [Option] the resulting Option containing a value modified by
|
163
|
+
# the supplied block
|
164
|
+
#
|
165
|
+
def collect(&block)
|
166
|
+
result = yield(@value)
|
167
|
+
result.nil? ? None.new : Some.new(result)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Counts the number of elements for which the block returns true
|
171
|
+
#
|
172
|
+
# @param block [Function] the function that determines whether the
|
173
|
+
# value should be counted
|
174
|
+
#
|
175
|
+
# @return [Int] 1 if the block returned true for this Option value or 0 if not
|
176
|
+
#
|
177
|
+
def count(&block)
|
178
|
+
yield(value) == true ? 1 : 0
|
179
|
+
end
|
180
|
+
|
181
|
+
# Determines if the current Option value satisfies the supplied block
|
182
|
+
#
|
183
|
+
# @param block [Function] the function that determines whether the
|
184
|
+
# value satisfies an expectation
|
185
|
+
#
|
186
|
+
# @return [Boolean] true if the block returns true for the value or false if not
|
187
|
+
#
|
188
|
+
def for_all(&block)
|
189
|
+
yield(@value)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Executes the provided block with the current Option value
|
193
|
+
#
|
194
|
+
# @param block [Function] the function that takes the current Option's value
|
195
|
+
#
|
196
|
+
# @return [Nil] nil
|
197
|
+
#
|
198
|
+
def for_each(&block)
|
199
|
+
yield(@value)
|
200
|
+
nil
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
class None < AbstractOption
|
205
|
+
def initialize
|
206
|
+
super(nil)
|
207
|
+
end
|
208
|
+
|
209
|
+
# Allows for the return of a replacement value
|
210
|
+
#
|
211
|
+
# @param block [Function] a block returning an alternate value
|
212
|
+
#
|
213
|
+
# @return [Any] the result of the supplied block
|
214
|
+
#
|
215
|
+
def get_or_else(&block)
|
216
|
+
yield
|
217
|
+
end
|
218
|
+
|
219
|
+
# Returns an alternative Option for the None
|
220
|
+
#
|
221
|
+
# @param v [Option] the option to be returned
|
222
|
+
#
|
223
|
+
# @return [Option] the provided alternate Option
|
224
|
+
#
|
225
|
+
def or_else(v)
|
226
|
+
validated_option_type(v)
|
227
|
+
end
|
228
|
+
|
229
|
+
# Maintains signiture parity with Some.map
|
230
|
+
#
|
231
|
+
# @param block [Function] the function which would be used to operate
|
232
|
+
# on the Option's value
|
233
|
+
#
|
234
|
+
# @return [None] a None
|
235
|
+
#
|
236
|
+
def map(&block)
|
237
|
+
self
|
238
|
+
end
|
239
|
+
|
240
|
+
# Indicates if the Option has a value
|
241
|
+
#
|
242
|
+
# @return [Boolean] true
|
243
|
+
#
|
244
|
+
def empty?
|
245
|
+
true
|
246
|
+
end
|
247
|
+
|
248
|
+
# Maintains signiture parity with Some.flat_map
|
249
|
+
#
|
250
|
+
# @param block [Function] the function which will operate on the
|
251
|
+
# Option's value (should return an Option)
|
252
|
+
#
|
253
|
+
# @return [RFunc::Option] a None
|
254
|
+
#
|
255
|
+
def flat_map(&block)
|
256
|
+
self
|
257
|
+
end
|
258
|
+
|
259
|
+
# Maintains signiture parity with Some.fold
|
260
|
+
#
|
261
|
+
# @param alternate [Any] the value to return if the Option is a None
|
262
|
+
# @param block [Function] the function which will operate on the
|
263
|
+
# current Option's value
|
264
|
+
#
|
265
|
+
# @return [Any] the alternate
|
266
|
+
#
|
267
|
+
def fold(alternate, &block)
|
268
|
+
alternate
|
269
|
+
end
|
270
|
+
|
271
|
+
# Maintains signiture parity with Some.flatten
|
272
|
+
#
|
273
|
+
# @return [None] self
|
274
|
+
#
|
275
|
+
def flatten
|
276
|
+
self
|
277
|
+
end
|
278
|
+
|
279
|
+
|
280
|
+
# Maintains signiture parity with Some.collect
|
281
|
+
#
|
282
|
+
# @param block [Function] the block that can be used to modify the value
|
283
|
+
# (should be a case statement with nil return for non operation)
|
284
|
+
#
|
285
|
+
# @return [None] self
|
286
|
+
#
|
287
|
+
def collect(&block)
|
288
|
+
self
|
289
|
+
end
|
290
|
+
|
291
|
+
# Counts the number of elements for which the block returns true
|
292
|
+
#
|
293
|
+
# @param block [Function] the function that determines whether the
|
294
|
+
# value should be counted
|
295
|
+
#
|
296
|
+
# @return [Int] 0 (there is no value to operate on)
|
297
|
+
#
|
298
|
+
def count(&block)
|
299
|
+
0
|
300
|
+
end
|
301
|
+
|
302
|
+
# Determines if the current Option value satisfies the supplied block
|
303
|
+
#
|
304
|
+
# @param block [Function] the function that determines whether the
|
305
|
+
# value satisfies an expectation
|
306
|
+
#
|
307
|
+
# @return [Boolean] true because the is no value to violate the supplied block
|
308
|
+
#
|
309
|
+
def for_all(&block)
|
310
|
+
true
|
311
|
+
end
|
312
|
+
|
313
|
+
# Returns nil (no value to execute on)
|
314
|
+
#
|
315
|
+
# @param block [Function] the function that takes the current Option's value
|
316
|
+
#
|
317
|
+
# @return [Nil] nil
|
318
|
+
#
|
319
|
+
def for_each(&block)
|
320
|
+
nil
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
module Option
|
325
|
+
def self.new(something_or_nothing)
|
326
|
+
case something_or_nothing.nil?
|
327
|
+
when false
|
328
|
+
Some.new(something_or_nothing)
|
329
|
+
else
|
330
|
+
None.new
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|