ramda-ruby 0.8.1 → 0.9.0
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 +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +29 -4
- data/ROADMAP.md +0 -12
- data/docs/FUNCTIONS.md +9 -0
- data/docs/RESOURCES.md +2 -0
- data/lib/ramda.rb +64 -172
- data/lib/ramda/function.rb +23 -44
- data/lib/ramda/internal/curried_method.rb +12 -55
- data/lib/ramda/internal/function_with_arity.rb +2 -2
- data/lib/ramda/internal/java/__make_curry_proc__.rb +33 -0
- data/lib/ramda/list.rb +38 -3
- data/lib/ramda/logic.rb +1 -1
- data/lib/ramda/object.rb +71 -11
- data/lib/ramda/version.rb +1 -1
- data/spec/ramda/function_spec.rb +38 -1
- data/spec/ramda/internal/curried_method_spec.rb +10 -4
- data/spec/ramda/list_spec.rb +37 -1
- data/spec/ramda/logic_spec.rb +1 -1
- data/spec/ramda/math_spec.rb +1 -1
- data/spec/ramda/object_spec.rb +100 -1
- data/spec/ramda/relation_spec.rb +1 -1
- data/spec/ramda/string_spec.rb +1 -1
- data/spec/ramda/type_spec.rb +1 -1
- data/spec/ramda_spec.rb +9 -0
- data/spec/spec_helper.rb +1 -0
- metadata +5 -2
@@ -5,17 +5,19 @@ module Ramda
|
|
5
5
|
# Curried Method
|
6
6
|
module CurriedMethod
|
7
7
|
def curried_method(name, &block)
|
8
|
-
|
8
|
+
define_method(name, &curried_method_body(name, block.arity, &block))
|
9
9
|
end
|
10
10
|
|
11
11
|
# rubocop:disable Metrics/MethodLength
|
12
12
|
def curried_method_body(name, arity, &block)
|
13
|
-
Ramda::Internal::FunctionWithArity.
|
13
|
+
Ramda::Internal::FunctionWithArity.call(arity) do |*args|
|
14
14
|
begin
|
15
|
-
if args.
|
15
|
+
if args.index(Ramda.__)
|
16
16
|
replace_placeholder(args, &block).curry
|
17
17
|
else
|
18
|
-
args.empty? ? block : yield(*args)
|
18
|
+
result = args.empty? ? block : yield(*args)
|
19
|
+
debug_log(name, args, result) if ::Ramda::DEBUG_MODE
|
20
|
+
result
|
19
21
|
end
|
20
22
|
rescue StandardError => e
|
21
23
|
::Ramda.exception_handler.call(e, name)
|
@@ -25,62 +27,17 @@ module Ramda
|
|
25
27
|
# rubocop:enable Metrics/MethodLength
|
26
28
|
|
27
29
|
def replace_placeholder(basic_args)
|
28
|
-
Ramda::Internal::FunctionWithArity.
|
30
|
+
Ramda::Internal::FunctionWithArity.call(basic_args.count(Ramda.__)) do |*new_args|
|
29
31
|
cloned_args = basic_args.dup
|
30
32
|
new_args.each { |arg| cloned_args[cloned_args.index(Ramda.__)] = arg }
|
31
|
-
yield(*cloned_args)
|
33
|
+
result = yield(*cloned_args)
|
34
|
+
debug_log(name, cloned_args, result) if ::Ramda::DEBUG_MODE
|
35
|
+
result
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
35
|
-
def
|
36
|
-
|
37
|
-
if args.empty?
|
38
|
-
block
|
39
|
-
else
|
40
|
-
yield(*args)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
define_singleton_method(name, &fn.curry)
|
45
|
-
end
|
46
|
-
|
47
|
-
def curried_method_v1(name, &block)
|
48
|
-
define_singleton_method(name) do |*args|
|
49
|
-
curried = block.curry
|
50
|
-
# curried.define_singleton_method(:origin_arity) { block.arity }
|
51
|
-
|
52
|
-
return curried if args.empty?
|
53
|
-
|
54
|
-
curried.call(*args)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
if RUBY_PLATFORM == 'java'
|
59
|
-
# This hack resolved issue:
|
60
|
-
# undefined method `__make_curry_proc__' for Ramda::Math:Module
|
61
|
-
#
|
62
|
-
# Source:
|
63
|
-
# https://github.com/jruby/jruby/issues/1523
|
64
|
-
#
|
65
|
-
# rubocop:disable Metrics/MethodLength
|
66
|
-
def __make_curry_proc__(proc, passed, arity)
|
67
|
-
is_lambda = proc.lambda?
|
68
|
-
passed.freeze
|
69
|
-
|
70
|
-
__send__((is_lambda ? :lambda : :proc)) do |*argv, &passed_proc|
|
71
|
-
my_passed = passed + argv
|
72
|
-
# original
|
73
|
-
# if my_passed.length < arity
|
74
|
-
# changed
|
75
|
-
if my_passed.length < arity.abs - 1
|
76
|
-
warn "#{caller[0]}: given block not used" unless passed_proc.nil?
|
77
|
-
__make_curry_proc__(proc, my_passed, arity)
|
78
|
-
else
|
79
|
-
proc.call(*my_passed)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
# rubocop:enable Metrics/MethodLength
|
39
|
+
def debug_log(name, args, result)
|
40
|
+
puts "-> #{name}(#{args.join(', ')}) # #{result}"
|
84
41
|
end
|
85
42
|
end
|
86
43
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Ramda
|
2
2
|
module Internal
|
3
3
|
# Curried Method
|
4
|
-
|
4
|
+
module FunctionWithArity
|
5
5
|
# rubocop:disable Metrics/CyclomaticComplexity
|
6
6
|
# rubocop:disable Metrics/MethodLength
|
7
7
|
# rubocop:disable Metrics/ParameterLists
|
8
|
-
def call(arity)
|
8
|
+
def self.call(arity)
|
9
9
|
case arity
|
10
10
|
when 0, -1
|
11
11
|
->(*a) { yield(*a) }
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Ramda
|
2
|
+
module Internal
|
3
|
+
module Java
|
4
|
+
# This hack resolved issue:
|
5
|
+
# undefined method `__make_curry_proc__' for Ramda::Math:Module
|
6
|
+
#
|
7
|
+
# Source:
|
8
|
+
# https://github.com/jruby/jruby/issues/1523
|
9
|
+
#
|
10
|
+
module MakeCurryProc
|
11
|
+
# rubocop:disable Metrics/MethodLength
|
12
|
+
def __make_curry_proc__(proc, passed, arity)
|
13
|
+
is_lambda = proc.lambda?
|
14
|
+
passed.freeze
|
15
|
+
|
16
|
+
__send__((is_lambda ? :lambda : :proc)) do |*argv, &passed_proc|
|
17
|
+
my_passed = passed + argv
|
18
|
+
# original
|
19
|
+
# if my_passed.length < arity
|
20
|
+
# changed
|
21
|
+
if my_passed.length < arity.abs - 1
|
22
|
+
warn "#{caller[0]}: given block not used" unless passed_proc.nil?
|
23
|
+
__make_curry_proc__(proc, my_passed, arity)
|
24
|
+
else
|
25
|
+
proc.call(*my_passed)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
# rubocop:enable Metrics/MethodLength
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/ramda/list.rb
CHANGED
@@ -97,6 +97,22 @@ module Ramda
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
+
# Returns a new list excluding the leading elements of a given list which
|
101
|
+
# satisfy the supplied predicate function. It passes each value to the
|
102
|
+
# supplied predicate function, skipping elements while the predicate
|
103
|
+
# function returns true. The predicate function is applied
|
104
|
+
# to one argument: (value).
|
105
|
+
#
|
106
|
+
# Dispatches to the dropWhile method of the second argument, if present.
|
107
|
+
#
|
108
|
+
# Acts as a transducer if a transformer is given in list position.
|
109
|
+
#
|
110
|
+
# (a -> Boolean) -> [a] -> [a]
|
111
|
+
#
|
112
|
+
curried_method(:drop_while) do |fn, xs|
|
113
|
+
xs.drop_while(&fn)
|
114
|
+
end
|
115
|
+
|
100
116
|
# Takes a predicate and a Filterable, and returns a new filterable of the same
|
101
117
|
# type containing the members of the given filterable which satisfy the given
|
102
118
|
# predicate. Filterable objects include plain objects or any object that
|
@@ -210,6 +226,15 @@ module Ramda
|
|
210
226
|
xs.index(x)
|
211
227
|
end
|
212
228
|
|
229
|
+
# Returns all but the last element of the given list or string.
|
230
|
+
#
|
231
|
+
# [a] -> [a]
|
232
|
+
# String -> String
|
233
|
+
#
|
234
|
+
curried_method(:init) do |xs|
|
235
|
+
xs[0..-2]
|
236
|
+
end
|
237
|
+
|
213
238
|
# Inserts the supplied element into the list, at the specified index.
|
214
239
|
# Note that this is not destructive: it returns a copy of the list with
|
215
240
|
# the changes. No lists have been harmed in the application of this function.
|
@@ -220,6 +245,16 @@ module Ramda
|
|
220
245
|
xs.dup.insert(idx, x)
|
221
246
|
end
|
222
247
|
|
248
|
+
# Inserts the sub-list into the list, at the specified index.
|
249
|
+
# Note that this is not destructive: it returns a copy of the list
|
250
|
+
# with the changes. No lists have been harmed in the application of this function.
|
251
|
+
#
|
252
|
+
# Number -> [a] -> [a] -> [a]
|
253
|
+
#
|
254
|
+
curried_method(:insert_all) do |index, elts, xs|
|
255
|
+
xs.dup.insert(index, *elts)
|
256
|
+
end
|
257
|
+
|
223
258
|
# Returns a string made by inserting the separator between each element and
|
224
259
|
# concatenating all the elements into a single string.
|
225
260
|
#
|
@@ -301,7 +336,7 @@ module Ramda
|
|
301
336
|
# Filterable f => (a -> Boolean) -> f a -> [f a, f a]
|
302
337
|
#
|
303
338
|
curried_method(:partition) do |fn, xs|
|
304
|
-
::Ramda.juxt([filter, reject]).call(fn, xs)
|
339
|
+
::Ramda.juxt([::Ramda.filter, ::Ramda.reject]).call(fn, xs)
|
305
340
|
end
|
306
341
|
|
307
342
|
# Returns a new list by plucking the same named property off all objects
|
@@ -425,7 +460,7 @@ module Ramda
|
|
425
460
|
# String -> String
|
426
461
|
#
|
427
462
|
curried_method(:tail) do |xs|
|
428
|
-
drop(1, xs)
|
463
|
+
::Ramda.drop(1, xs)
|
429
464
|
end
|
430
465
|
|
431
466
|
# Returns the first n elements of the given list, string.
|
@@ -478,7 +513,7 @@ module Ramda
|
|
478
513
|
# Chain c => c (c a) -> c a
|
479
514
|
#
|
480
515
|
curried_method(:unnest) do |xs|
|
481
|
-
Ramda.chain(Ramda.identity, xs)
|
516
|
+
::Ramda.chain(::Ramda.identity, xs)
|
482
517
|
end
|
483
518
|
|
484
519
|
# Returns a new copy of the array with the element at the provided
|
data/lib/ramda/logic.rb
CHANGED
@@ -26,7 +26,7 @@ module Ramda
|
|
26
26
|
# (*... -> *) -> (*... -> Boolean)
|
27
27
|
#
|
28
28
|
curried_method(:complement) do |fn|
|
29
|
-
::Ramda::Internal::FunctionWithArity.
|
29
|
+
::Ramda::Internal::FunctionWithArity.call(fn.arity) do |*args|
|
30
30
|
!fn.call(*args)
|
31
31
|
end.curry
|
32
32
|
end
|
data/lib/ramda/object.rb
CHANGED
@@ -33,7 +33,7 @@ module Ramda
|
|
33
33
|
if path.empty?
|
34
34
|
val
|
35
35
|
else
|
36
|
-
cloned = clone(obj)
|
36
|
+
cloned = ::Ramda.clone(obj)
|
37
37
|
path[0...-1].reduce(cloned) do |acc, k|
|
38
38
|
case acc[k]
|
39
39
|
when Hash, Array
|
@@ -56,10 +56,10 @@ module Ramda
|
|
56
56
|
case obj
|
57
57
|
when Hash
|
58
58
|
obj.each_with_object(obj.dup) do |(key, value), acc|
|
59
|
-
acc[clone(key)] = clone(value)
|
59
|
+
acc[::Ramda.clone(key)] = ::Ramda.clone(value)
|
60
60
|
end
|
61
61
|
when Array
|
62
|
-
obj.map(
|
62
|
+
obj.map(&::Ramda.clone)
|
63
63
|
when Symbol, Integer, NilClass, TrueClass, FalseClass
|
64
64
|
obj
|
65
65
|
else
|
@@ -72,7 +72,7 @@ module Ramda
|
|
72
72
|
# String -> {k: v} -> {k: v}
|
73
73
|
#
|
74
74
|
curried_method(:dissoc) do |prop, obj|
|
75
|
-
clone(obj).tap { |o| o.delete(prop) }
|
75
|
+
::Ramda.clone(obj).tap { |o| o.delete(prop) }
|
76
76
|
end
|
77
77
|
|
78
78
|
# Returns whether or not an object has an own property with the specified name
|
@@ -101,6 +101,56 @@ module Ramda
|
|
101
101
|
a[prop] == b[prop]
|
102
102
|
end
|
103
103
|
|
104
|
+
# Creates a new object by recursively evolving a shallow copy of object,
|
105
|
+
# according to the transformation functions. All non-primitive properties
|
106
|
+
# are copied by reference.
|
107
|
+
#
|
108
|
+
# A transformation function will not be invoked if its corresponding
|
109
|
+
# key does not exist in the evolved object.
|
110
|
+
#
|
111
|
+
# {k: (v -> v)} -> {k: v} -> {k: v}
|
112
|
+
#
|
113
|
+
curried_method(:evolve) do |trans, obj|
|
114
|
+
obj.each_with_object({}) do |(key, val), acc|
|
115
|
+
acc[key] = case trans[key]
|
116
|
+
when Hash
|
117
|
+
::Ramda.evolve(trans[key], val)
|
118
|
+
when Proc
|
119
|
+
trans[key].call(val)
|
120
|
+
else
|
121
|
+
val
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Same as R.invertObj, however this accounts for objects with duplicate
|
127
|
+
# values by putting the values into an array.
|
128
|
+
#
|
129
|
+
# {s: x} -> {x: [ s, ...]}
|
130
|
+
#
|
131
|
+
curried_method(:invert) do |obj|
|
132
|
+
case obj
|
133
|
+
when Hash
|
134
|
+
# Ramda.map(Ramda.map(:first.to_proc), obj.group_by { |_, v| v })
|
135
|
+
Hash[obj.group_by { |_, v| v }.map { |k, v| [k, v.map(&:first)] }]
|
136
|
+
when Array
|
137
|
+
Hash[obj.each_with_index.group_by { |v, _| v }.map { |k, v| [k, v.map(&:last)] }]
|
138
|
+
else
|
139
|
+
{}
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
curried_method(:invert_obj) do |obj|
|
144
|
+
case obj
|
145
|
+
when Hash
|
146
|
+
obj.invert
|
147
|
+
when Array
|
148
|
+
Hash[obj.each_with_index.map { |k, v| [k, v] }]
|
149
|
+
else
|
150
|
+
{}
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
104
154
|
# Returns a list containing the names of all the enumerable own properties
|
105
155
|
# of the supplied object.
|
106
156
|
# Note that the order of the output array is not guaranteed.
|
@@ -132,7 +182,7 @@ module Ramda
|
|
132
182
|
#
|
133
183
|
curried_method(:lens) do |getter, setter|
|
134
184
|
curried_method_body(:lens, 2) do |to_functor_fn, target|
|
135
|
-
Ramda.map(
|
185
|
+
::Ramda.map(
|
136
186
|
->(focus) { setter.call(focus, target) },
|
137
187
|
to_functor_fn.call(getter.call(target))
|
138
188
|
)
|
@@ -145,7 +195,7 @@ module Ramda
|
|
145
195
|
# Lens s a = Functor f => (a -> f a) -> s -> f s
|
146
196
|
#
|
147
197
|
curried_method(:lens_index) do |n|
|
148
|
-
lens(Ramda.nth(0), Ramda.update(n))
|
198
|
+
::Ramda.lens(::Ramda.nth(0), ::Ramda.update(n))
|
149
199
|
end
|
150
200
|
|
151
201
|
# Returns a lens whose focus is the specified path.
|
@@ -155,7 +205,7 @@ module Ramda
|
|
155
205
|
# Lens s a = Functor f => (a -> f a) -> s -> f s
|
156
206
|
#
|
157
207
|
curried_method(:lens_path) do |path|
|
158
|
-
lens(Ramda.path(path), Ramda.assoc_path(path))
|
208
|
+
::Ramda.lens(Ramda.path(path), Ramda.assoc_path(path))
|
159
209
|
end
|
160
210
|
|
161
211
|
# Returns a lens whose focus is the specified property.
|
@@ -164,7 +214,17 @@ module Ramda
|
|
164
214
|
# Lens s a = Functor f => (a -> f a) -> s -> f s
|
165
215
|
#
|
166
216
|
curried_method(:lens_prop) do |k|
|
167
|
-
lens(Ramda.prop(k), Ramda.assoc(k))
|
217
|
+
::Ramda.lens(Ramda.prop(k), Ramda.assoc(k))
|
218
|
+
end
|
219
|
+
|
220
|
+
# An Object-specific version of map. The function is applied to
|
221
|
+
# three arguments: (value, key, obj).
|
222
|
+
# If only the value is significant, use map instead.
|
223
|
+
#
|
224
|
+
# ((*, String, Object) -> *) -> Object -> Object
|
225
|
+
#
|
226
|
+
curried_method(:map_obj_indexed) do |fn, obj|
|
227
|
+
Hash[obj.map { |(k, v)| [k, fn.call(v, k, obj)] }]
|
168
228
|
end
|
169
229
|
|
170
230
|
# Create a new object with the own properties of the first object merged
|
@@ -182,7 +242,7 @@ module Ramda
|
|
182
242
|
# [String] -> {String: *} -> {String: *}
|
183
243
|
#
|
184
244
|
curried_method(:omit) do |keys, obj|
|
185
|
-
obj_copy = clone(obj)
|
245
|
+
obj_copy = ::Ramda.clone(obj)
|
186
246
|
keys.each(&obj_copy.method(:delete))
|
187
247
|
obj_copy
|
188
248
|
end
|
@@ -244,7 +304,7 @@ module Ramda
|
|
244
304
|
# [k] -> [{k: v}] -> [{k: v}]
|
245
305
|
#
|
246
306
|
curried_method(:project) do |keys, objs|
|
247
|
-
objs.map(
|
307
|
+
objs.map(&::Ramda.pick_all(keys))
|
248
308
|
end
|
249
309
|
|
250
310
|
# Returns a function that when supplied an object returns the indicated
|
@@ -287,7 +347,7 @@ module Ramda
|
|
287
347
|
# Lens s a = Functor f => (a -> f a) -> s -> f s
|
288
348
|
#
|
289
349
|
curried_method(:set) do |lens, v, x|
|
290
|
-
over(lens, Ramda.always(v), x)
|
350
|
+
::Ramda.over(lens, Ramda.always(v), x)
|
291
351
|
end
|
292
352
|
|
293
353
|
# Converts an object into an array of key, value arrays. Only the
|
data/lib/ramda/version.rb
CHANGED
data/spec/ramda/function_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Ramda::Function do
|
4
|
-
let(:r) {
|
4
|
+
let(:r) { Ramda }
|
5
5
|
|
6
6
|
context '#F' do
|
7
7
|
it 'from docs' do
|
@@ -85,6 +85,35 @@ describe Ramda::Function do
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
+
context '#call' do
|
89
|
+
it 'from docs' do
|
90
|
+
indent_n = R.pipe(R.times(R.always(' ')),
|
91
|
+
R.join(''),
|
92
|
+
R.replace(/^(?!$)/m))
|
93
|
+
|
94
|
+
format = R.converge(R.call, [
|
95
|
+
R.pipe(R.prop(:indent), indent_n),
|
96
|
+
R.prop(:value)
|
97
|
+
])
|
98
|
+
|
99
|
+
expect(format.call(indent: 2, value: "foo\nbar\nbaz\n")).to eq(" foo\n bar\n baz\n")
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns the result of calling its first argument with the remaining arguments' do
|
103
|
+
fn = ->(*args) { args.max }
|
104
|
+
expect(R.call(fn, 1, 2, 3, -99, 42, 6, 7)).to eq(42)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'accepts one or more arguments' do
|
108
|
+
fn = ->(*args) { args.length; }
|
109
|
+
|
110
|
+
expect(R.call(fn)).to eq(0)
|
111
|
+
expect(R.call(fn, 'x')).to eq(1)
|
112
|
+
expect(R.call(fn, 'x', 'y')).to eq(2)
|
113
|
+
expect(R.call(fn, 'x', 'y', 'z')).to eq(3)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
88
117
|
context '#comparator' do
|
89
118
|
it 'from docs' do
|
90
119
|
sort_rule = r.comparator(->(a, b) { a < b })
|
@@ -355,6 +384,14 @@ describe Ramda::Function do
|
|
355
384
|
end
|
356
385
|
end
|
357
386
|
|
387
|
+
context '#nth_arg' do
|
388
|
+
it 'from docs' do
|
389
|
+
expect(R.nth_arg(1, 'a', 'b', 'c')).to eq('b')
|
390
|
+
expect(R.nth_arg(1).call('a', 'b', 'c')).to eq('b')
|
391
|
+
expect(R.nth_arg(-1).call('a', 'b', 'c')).to eq('c')
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
358
395
|
context '#of' do
|
359
396
|
it 'from docs' do
|
360
397
|
expect(r.of(nil)).to eq([nil])
|