ramda-ruby 0.1.0.alpha

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.
@@ -0,0 +1,16 @@
1
+ module Ramda
2
+ module Internal
3
+ # Curried Method
4
+ module CurriedMethod
5
+ def curried_method(name, &block)
6
+ define_singleton_method(name) do |*args|
7
+ curried = block.curry
8
+
9
+ return curried if args.empty?
10
+
11
+ curried.call(*args)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ module Ramda
2
+ module Internal
3
+ # Curried Method
4
+ class FunctionWithArity
5
+ # rubocop:disable Metrics/CyclomaticComplexity
6
+ # rubocop:disable Metrics/MethodLength
7
+ # rubocop:disable Metrics/ParameterLists
8
+ def call(arity)
9
+ case arity
10
+ when 0
11
+ ->(*a) { yield(*a) }
12
+ when 1
13
+ ->(a, *b) { yield(a, *b) }
14
+ when 2
15
+ ->(a, b, *c) { yield(a, b, *c) }
16
+ when 3
17
+ ->(a, b, c, *d) { yield(a, b, c, *d) }
18
+ when 4
19
+ ->(a, b, c, d, *e) { yield(a, b, c, d, *e) }
20
+ when 5
21
+ ->(a, b, c, d, e, *f) { yield(a, b, c, d, e, *f) }
22
+ when 6
23
+ ->(a, b, c, d, e, f, *g) { yield(a, b, c, d, e, f, *g) }
24
+ else
25
+ raise ArgumentError, "Arrity #{arity} is not supported"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
data/lib/ramda/list.rb ADDED
@@ -0,0 +1,372 @@
1
+ require_relative 'internal/curried_method'
2
+
3
+ module Ramda
4
+ # List functions
5
+ # rubocop:disable Metrics/ModuleLength
6
+ module List
7
+ extend ::Ramda::Internal::CurriedMethod
8
+
9
+ # Returns true if all elements of the list match the predicate,
10
+ # false if there are any that don't.
11
+ # Dispatches to the all method of the second argument, if present.
12
+ # Acts as a transducer if a transformer is given in list position.
13
+ #
14
+ # (a -> Boolean) -> [a] -> Boolean
15
+ #
16
+ curried_method(:all) do |f, xs|
17
+ xs.all?(&f)
18
+ end
19
+
20
+ # Returns true if at least one of elements of the list match the predicate,
21
+ # false otherwise.
22
+ # Dispatches to the any method of the second argument, if present.
23
+ # Acts as a transducer if a transformer is given in list position.
24
+ #
25
+ # (a -> Boolean) -> [a] -> Boolean
26
+ #
27
+ curried_method(:any) do |f, xs|
28
+ xs.any?(&f)
29
+ end
30
+
31
+ # Returns a new list containing the contents of the given list,
32
+ # followed by the given element.
33
+ #
34
+ # a -> [a] -> [a]
35
+ #
36
+ curried_method(:append) do |x, xs|
37
+ xs.dup + [x]
38
+ end
39
+
40
+ # Returns the result of concatenating the given lists or strings.
41
+ # String -> String -> String
42
+ #
43
+ # List -> List -> List
44
+ #
45
+ curried_method(:concat) do |list_a, list_b|
46
+ case list_a
47
+ when ::String, ::Symbol
48
+ [list_a, list_b].join('')
49
+ when ::Array
50
+ list_a.dup + list_b
51
+ else
52
+ type_error(list_a, :concat)
53
+ end
54
+ end
55
+
56
+ # Returns true if the specified value is equal, in R.equals terms,
57
+ # to at least one element of the given list; false otherwise.
58
+ #
59
+ # a -> [a] -> Boolean
60
+ #
61
+ curried_method(:contains) do |x, xs|
62
+ xs.include?(x)
63
+ end
64
+
65
+ # Returns all but the first n elements of the given list, string,
66
+ # or transducer/transformer (or object with a drop method).
67
+ #
68
+ # Number -> [a] -> [a]
69
+ # Number -> String -> String
70
+ #
71
+ curried_method(:drop) do |num, xs|
72
+ case xs
73
+ when ::String
74
+ xs[num..-1] || ''
75
+ when ::Array
76
+ xs[num..-1] || []
77
+ else
78
+ type_error(xs, :drop)
79
+ end
80
+ end
81
+
82
+ # Takes a predicate and a Filterable, and returns a new filterable of the same
83
+ # type containing the members of the given filterable which satisfy the given
84
+ # predicate. Filterable objects include plain objects or any object that
85
+ # has a filter method such as Array.
86
+ # Dispatches to the filter method of the second argument, if present.
87
+ #
88
+ # Filterable f => (a -> Boolean) -> f a -> f a
89
+ #
90
+ curried_method(:filter) do |f, xs|
91
+ case xs
92
+ when ::Hash
93
+ xs.select { |_, value| f.call(value) }
94
+ else
95
+ xs.select(&f)
96
+ end
97
+ end
98
+
99
+ # Returns the first element of the list which matches the predicate,
100
+ # or undefined if no element matches.
101
+ #
102
+ # (a -> Boolean) -> [a] -> a | NilClass
103
+ #
104
+ curried_method(:find) do |f, xs|
105
+ xs.find(&f)
106
+ end
107
+
108
+ # Returns a new list by pulling every item out of it (and all its sub-arrays)
109
+ # and putting them in a new array, depth-first.
110
+ #
111
+ # [a] -> [b]
112
+ #
113
+ curried_method(:flatten, &:flatten)
114
+
115
+ # Splits a list into sub-lists stored in an object, based on the result of
116
+ # calling a String-returning function on each element, and grouping the
117
+ # results according to values returned.
118
+ #
119
+ # (a -> String) -> [a] -> {String: [a]}
120
+ #
121
+ curried_method(:group_by) do |f, xs|
122
+ xs.group_by(&f)
123
+ end
124
+
125
+ # Returns the first element of the given list or string. In some libraries
126
+ # this function is named first.
127
+ #
128
+ # [a] -> a | NilClass
129
+ # String -> String
130
+ #
131
+ curried_method(:head) do |x|
132
+ case x
133
+ when ::String
134
+ x[0] || ''
135
+ else
136
+ x[0]
137
+ end
138
+ end
139
+
140
+ # Returns the position of the first occurrence of an item in an array,
141
+ # or -1 if the item is not included in the array.
142
+ #
143
+ # a -> [a] -> Number
144
+ #
145
+ curried_method(:index_of) do |x, xs|
146
+ xs.index(x) || -1
147
+ end
148
+
149
+ # Returns a string made by inserting the separator between each element and
150
+ # concatenating all the elements into a single string.
151
+ #
152
+ # String -> [a] -> String
153
+ #
154
+ curried_method(:join) do |separator, xs|
155
+ xs.join(separator)
156
+ end
157
+
158
+ # Returns the position of the last occurrence of an item in an array,
159
+ # or -1 if the item is not included in the array.
160
+ #
161
+ # a -> [a] -> Number
162
+ #
163
+ curried_method(:last_index_of) do |x, xs|
164
+ xs.rindex(x) || -1
165
+ end
166
+
167
+ # Returns the number of elements in the array by returning list.length
168
+ #
169
+ # [a] -> Number
170
+ #
171
+ curried_method(:length, &:size)
172
+
173
+ # Takes a function and a functor, applies the function to each of the
174
+ # functor's values, and returns a functor of the same shape.
175
+ # Ramda provides suitable map implementations for Array and Object,
176
+ # so this function may be applied to [1, 2, 3] or {x: 1, y: 2, z: 3}.
177
+ #
178
+ # Functor f => (a -> b) -> f a -> f b
179
+ #
180
+ curried_method(:map) do |f, functor|
181
+ case functor
182
+ when ::Hash
183
+ Hash[functor.map { |k, v| [k, f.call(v)] }]
184
+ when ::Array
185
+ functor.map(&f)
186
+ else
187
+ type_error(functor, :map)
188
+ end
189
+ end
190
+
191
+ # Returns the nth element of the given list or string. If n is negative
192
+ # the element at index length + n is returned.
193
+ #
194
+ # Number -> [a] -> a | NilClass
195
+ # Number -> String -> String
196
+ #
197
+ curried_method(:nth) do |index, xs|
198
+ case xs
199
+ when ::String
200
+ xs[index] || ''
201
+ when ::Array
202
+ xs[index]
203
+ else
204
+ type_error(xs, :nth)
205
+ end
206
+ end
207
+
208
+ # Returns a new list by plucking the same named property off all objects
209
+ # in the list supplied.
210
+ #
211
+ # Pluck will work on any functor in addition to arrays, as it is equivalent
212
+ # to R.map(R.prop(k), f).
213
+ #
214
+ # Functor f => k -> f {k: v} -> f v
215
+ #
216
+ curried_method(:pluck) do |key, xs|
217
+ xs.map { |x| x[key] }
218
+ end
219
+
220
+ # Returns a new list with the given element at the front, followed by the
221
+ # contents of the list.
222
+ #
223
+ # a -> [a] -> [a]
224
+ #
225
+ curried_method(:prepend) do |x, xs|
226
+ [x] + xs.dup
227
+ end
228
+
229
+ # Returns a list of numbers from from (inclusive) to to (exclusive).
230
+ #
231
+ # Number -> Number -> [Number]
232
+ #
233
+ curried_method(:range) do |a, b|
234
+ (a...b).to_a
235
+ end
236
+
237
+ # Returns a single item by iterating through the list, successively
238
+ # calling the iterator function and passing it an accumulator value
239
+ # and the current value from the array, and then passing the result
240
+ # to the next call.
241
+ #
242
+ # The iterator function receives two values: (value, acc),
243
+ # while the arguments' order of reduce's iterator function is (acc, value).
244
+ #
245
+ # ((a, b) -> a) -> a -> [b] -> a
246
+ #
247
+ curried_method(:reduce) do |fn, acc, xs|
248
+ xs.reduce(acc, &fn)
249
+ end
250
+
251
+ # Returns a single item by iterating through the list, successively
252
+ # calling the iterator function and passing it an accumulator value
253
+ # and the current value from the array, and then passing the result
254
+ # to the next call.
255
+ # Similar to reduce, except moves through the input list from the
256
+ # right to the left.
257
+ #
258
+ # The iterator function receives two values: (value, acc),
259
+ # while the arguments' order of reduce's iterator function is (acc, value).
260
+ #
261
+ # ((a, b) -> a) -> a -> [b] -> a
262
+ #
263
+ curried_method(:reduce_right) do |fn, acc_arg, xs|
264
+ xs.reverse.reduce(acc_arg) { |acc, x| fn.call(x, acc) }
265
+ end
266
+
267
+ # Returns a new list or string with the elements or characters in reverse order.
268
+ #
269
+ # [a] -> [a]
270
+ # String -> String
271
+ #
272
+ curried_method(:reverse, &:reverse)
273
+
274
+ # The complement of filter.
275
+ # Acts as a transducer if a transformer is given in list position.
276
+ # Filterable objects include plain objects or any object that has a
277
+ # filter method such as Array.
278
+ #
279
+ # Filterable f => (a -> Boolean) -> f a -> f a
280
+ #
281
+ curried_method(:reject) do |f, xs|
282
+ case xs
283
+ when ::Hash
284
+ xs.reject { |_, value| f.call(value) }
285
+ else
286
+ xs.reject(&f)
287
+ end
288
+ end
289
+
290
+ # Returns a copy of the list, sorted according to the comparator function,
291
+ # which should accept two values at a time and return a negative number
292
+ # if the first value is smaller, a positive number if it's larger, and
293
+ # zero if they are equal. Please note that this is a copy of the list.
294
+ # It does not modify the original.
295
+
296
+ curried_method(:sort) do |comparator, xs|
297
+ xs.sort(&comparator)
298
+ end
299
+
300
+ # Returns all but the first element of the given list or string
301
+ # (or object with a tail method).
302
+ #
303
+ # [a] -> [a]
304
+ # String -> String
305
+ #
306
+ curried_method(:tail) do |xs|
307
+ drop(1, xs)
308
+ end
309
+
310
+ # Returns the first n elements of the given list, string.
311
+ #
312
+ # Number -> [a] -> [a]
313
+ # Number -> String -> String
314
+ #
315
+ curried_method(:take) do |num, xs|
316
+ xs[0, num]
317
+ end
318
+
319
+ # Returns a new list containing the first n elements of a given list,
320
+ # passing each value to the supplied predicate function, and terminating
321
+ # when the predicate function returns false. Excludes the element that
322
+ # caused the predicate function to fail.
323
+ # The predicate function is passed one argument: (value).
324
+ #
325
+ # (a -> Boolean) -> [a] -> [a]
326
+ #
327
+ curried_method(:take_while) do |fn, xs|
328
+ xs[0, xs.index { |x| !fn.call(x) } || xs.size]
329
+ end
330
+
331
+ # Returns a new list containing only one copy of each element in the original list.
332
+ #
333
+ # [a] -> [a]
334
+ #
335
+ curried_method(:uniq, &:uniq)
336
+
337
+ # Creates a new list out of the two supplied by creating each possible pair
338
+ # from the lists.
339
+ #
340
+ # [a] -> [b] -> [[a,b]]
341
+ #
342
+ curried_method(:xprod) do |xs1, xs2|
343
+ xs1.product(xs2)
344
+ end
345
+
346
+ # Creates a new list out of the two supplied by pairing up equally-positioned
347
+ # items from both lists. The returned list is truncated to the length of the
348
+ # shorter of the two input lists.
349
+ # Note: zip is equivalent to zip_with(->(a, b) { [a, b] }).
350
+ #
351
+ # [a] -> [b] -> [[a,b]]
352
+ #
353
+ curried_method(:zip) do |xs1, xs2|
354
+ xs1.zip(xs2)
355
+ end
356
+
357
+ # Creates a new list out of the two supplied by applying the function to each
358
+ # equally-positioned pair in the lists. The returned list is truncated to the
359
+ # length of the shorter of the two input lists.
360
+ #
361
+ # (a,b -> c) -> [a] -> [b] -> [c]
362
+ #
363
+ curried_method(:zip_with) do |fn, xs1, xs2|
364
+ xs1.zip(xs2).map { |(a, b)| fn.call(a, b) }
365
+ end
366
+
367
+ # TODO: Extract from this module
368
+ def self.type_error(object, method)
369
+ raise ArgumentError, "Unexpected type #{object.class} in method: #{method}"
370
+ end
371
+ end
372
+ end
@@ -0,0 +1,58 @@
1
+ require_relative 'internal/curried_method'
2
+
3
+ module Ramda
4
+ # Logic functions
5
+ module Logic
6
+ extend ::Ramda::Internal::CurriedMethod
7
+
8
+ curried_method(:all_pass) do |predicates, obj|
9
+ predicates.all? { |predicate| predicate.call(obj) }
10
+ end
11
+
12
+ curried_method(:and) do |a, b|
13
+ a && b
14
+ end
15
+
16
+ curried_method(:any_pass) do |predicates, obj|
17
+ predicates.any? { |predicate| predicate.call(obj) }
18
+ end
19
+
20
+ # Creates a function that will process either the onTrue or the onFalse
21
+ # function depending upon the result of the condition predicate.
22
+ #
23
+ # (*... -> Boolean) -> (*... -> *) -> (*... -> *) -> (*... -> *)
24
+ #
25
+ curried_method(:if_else) do |predicate, fn1, fn2, obj|
26
+ predicate.call(obj) ? fn1.call(obj) : fn2.call(obj)
27
+ end
28
+
29
+ # Returns true if the given value is its type's empty value; false otherwise.
30
+ #
31
+ # a -> Boolean
32
+ #
33
+ curried_method(:is_empty) do |el|
34
+ case el
35
+ when ::NilClass, ::Integer
36
+ false
37
+ else
38
+ el.empty?
39
+ end
40
+ end
41
+
42
+ # A function that returns the ! of its argument. It will return true when
43
+ # passed false-y value, and false when passed a truth-y one.
44
+ #
45
+ # * -> Boolean
46
+ #
47
+ curried_method(:not, &:!)
48
+
49
+ # Returns true if one or both of its arguments are true. Returns false if
50
+ # both arguments are false.
51
+ #
52
+ # a -> b -> a | b
53
+ #
54
+ curried_method(:or) do |a, b|
55
+ a || b
56
+ end
57
+ end
58
+ end