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.
- checksums.yaml +7 -0
- data/.bashrc.docker +2 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +14 -0
- data/.overcommit.yml +73 -0
- data/.pryrc.docker +1 -0
- data/.rspec +2 -0
- data/.rubocop.yml +42 -0
- data/.travis.yml +35 -0
- data/CHANGELOG.md +3 -0
- data/Dockerfile +24 -0
- data/Gemfile +23 -0
- data/Gemfile.dev +6 -0
- data/Gemfile.dev.lock +38 -0
- data/LICENSE.txt +21 -0
- data/README.md +68 -0
- data/ROADMAP.md +14 -0
- data/Rakefile +6 -0
- data/appveyor.yml +26 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/codeclimate.yml +6 -0
- data/docker-compose.override.yml +12 -0
- data/docker-compose.yml +15 -0
- data/docs/FUNCTIONS.md +93 -0
- data/lib/ramda.rb +123 -0
- data/lib/ramda/function.rb +181 -0
- data/lib/ramda/internal/curried_method.rb +16 -0
- data/lib/ramda/internal/function_with_arity.rb +30 -0
- data/lib/ramda/list.rb +372 -0
- data/lib/ramda/logic.rb +58 -0
- data/lib/ramda/math.rb +72 -0
- data/lib/ramda/object.rb +110 -0
- data/lib/ramda/relation.rb +161 -0
- data/lib/ramda/string.rb +49 -0
- data/lib/ramda/version.rb +3 -0
- data/ramda-ruby.gemspec +24 -0
- metadata +80 -0
@@ -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
|
data/lib/ramda/logic.rb
ADDED
@@ -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
|