ramda-ruby 0.7.0 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a23c9651684d48d741ff366c825cc13eb8b88b03
4
- data.tar.gz: f784df378ef790ed8ac918986294b983500c2c8d
3
+ metadata.gz: 28285eadf06563393e23d6cff7ad2f945a6b579e
4
+ data.tar.gz: 6efe04a0ec2340fa87d43ffcedf6b56b8c949ce8
5
5
  SHA512:
6
- metadata.gz: 5578f41adcd7d4978b8c3a3be2d80e4ab2f61d9e45e0f6ac46fa1b30354a53475fef02e18c06c32816f5bf8384959b6a9a1147b6df51b67519d3179f63de678b
7
- data.tar.gz: 356cfffa686a4e1853353600e72076e25073262442497695a518be6699f9b91c344dc3a898dc22c1ad14a55abd0db22be1779c29e2ad7af626b92fbd3658a265
6
+ metadata.gz: a8e29a9fceca691c212931de21d6c7972a17d4ff4f151ed0afb6457d3e6f4113a78498b209de824ce32ec40b46bb5f974c779a2728bcee8b86f70faaac3c4ccb
7
+ data.tar.gz: 7f525b162fd911a9117cbedcfcebe662af36b11345130eaa9faf15e67fbeff65c06a5297059c6cdc60a0f95e7c63f20b737053cf24f6e86c45664cfa7d802cf5
@@ -1,6 +1,27 @@
1
1
  Not Released
2
2
  ---------------
3
3
 
4
+ Release 0.8.0
5
+ ---------------
6
+
7
+ Added:
8
+
9
+ * assoc_path
10
+ * lens - composition does not work compose(lens1, lensb)
11
+ * lens_index
12
+ * lens_path
13
+ * lens_prop
14
+ * max_by
15
+ * min_by
16
+ * negate
17
+ * over
18
+ * pick_by
19
+ * set
20
+ * type
21
+ * unapply
22
+ * view
23
+ * update
24
+
4
25
  Release 0.7.0
5
26
  ---------------
6
27
 
@@ -20,7 +41,7 @@ Added:
20
41
 
21
42
  * F
22
43
  * T
23
- * __ - first function call should have all arguments g(___2, __)(1, 3), this means that it doesn't support g(__, 2)(1)(3), g(__, 2)(1, 3) and g(__, 2)(__, 3)(1)
44
+ * `__` - first function call should have all arguments `g(__2, __)(1, 3)`, this means that it doesn't support `g(__, 2)(1)(3)`, `g(__, 2)(1, 3)` and `g(__, 2)(__, 3)(1)`
24
45
  * bind
25
46
  * cond
26
47
  * prop_or
data/ROADMAP.md CHANGED
@@ -4,16 +4,6 @@
4
4
 
5
5
  ### release 0.8.0
6
6
 
7
- * assoc
8
- * assoc_path
9
- * if_else
10
- * lens
11
- * max_by
12
- * min_by
13
- * pick_by
14
- * type
15
- * unapply
16
-
17
7
  ### release 0.9.0
18
8
 
19
9
  * all_pass
@@ -4,7 +4,7 @@
4
4
  * (pending) values_in
5
5
  * F
6
6
  * T
7
- * __ - first function call should have all arguments g(___2, __)(1, 3), this means that it doesn't support g(__, 2)(1)(3), g(__, 2)(1, 3) and g(__, 2)(__, 3)(1)
7
+ * `__` - first function call should have all arguments `g(__2, __)(1, 3)`, this means that it doesn't support `g(__, 2)(1)(3)`, `g(__, 2)(1, 3)` and `g(__, 2)(__, 3)(1)`
8
8
  * add
9
9
  * all
10
10
  * all_pass
@@ -16,6 +16,7 @@
16
16
  * append
17
17
  * apply
18
18
  * assoc
19
+ * assoc_path
19
20
  * binary
20
21
  * bind
21
22
  * chain
@@ -73,6 +74,10 @@
73
74
  * last
74
75
  * last_index_of - returns nil if index doesn't exist
75
76
  * length
77
+ * lens - composition does not work compose(lens1, lensb)
78
+ * lens_index
79
+ * lens_path
80
+ * lens_prop
76
81
  * lift
77
82
  * lift_n
78
83
  * lt
@@ -80,23 +85,28 @@
80
85
  * map
81
86
  * match
82
87
  * max
88
+ * max_by
83
89
  * memoize
84
90
  * merge
85
91
  * min
92
+ * min_by
86
93
  * modulo
87
94
  * multiply
88
95
  * n_ary
96
+ * negate
89
97
  * not
90
98
  * nth
91
99
  * of
92
100
  * omit
93
101
  * once
94
102
  * or
103
+ * over
95
104
  * partition
96
105
  * path
97
106
  * path_eq
98
107
  * pick
99
108
  * pick_all
109
+ * pick_by
100
110
  * pipe
101
111
  * pluck
102
112
  * prepend
@@ -114,6 +124,7 @@
114
124
  * repeat
115
125
  * replace - it uses a gsub method and global replacement
116
126
  * reverse
127
+ * set
117
128
  * slice
118
129
  * sort
119
130
  * sort_by
@@ -129,14 +140,18 @@
129
140
  * to_pairs
130
141
  * to_upper
131
142
  * trim
143
+ * type
144
+ * unapply
132
145
  * unary
133
146
  * union
134
147
  * union_with
135
148
  * uniq
136
149
  * uniq_with - first argument is a function with 1 arity which transforms each list element and applies uniq function to results
137
150
  * unnest
151
+ * update
138
152
  * use_with
139
153
  * values
154
+ * view
140
155
  * where
141
156
  * xprod
142
157
  * zip
@@ -44,6 +44,7 @@ module Ramda
44
44
  :once,
45
45
  :pipe,
46
46
  :tap,
47
+ :unapply,
47
48
  :unary,
48
49
  :use_with
49
50
 
@@ -92,6 +93,7 @@ module Ramda
92
93
  :uniq,
93
94
  :uniq_with,
94
95
  :unnest,
96
+ :update,
95
97
  :xprod,
96
98
  :zip,
97
99
  :zip_obj,
@@ -109,39 +111,49 @@ module Ramda
109
111
  :or
110
112
 
111
113
  def_delegators Ramda::Math,
114
+ # :math_mod,
112
115
  :add,
113
116
  :dec,
114
117
  :divide,
115
118
  :inc,
116
- # :math_mod,
117
119
  :modulo,
118
120
  :multiply,
121
+ :negate,
119
122
  :product,
120
123
  :subtract,
121
124
  :sum
122
125
 
123
126
  def_delegators Ramda::Object,
127
+ # :keys_in,
128
+ # :to_pairs_in,
129
+ # :values_in,
124
130
  :assoc,
131
+ :assoc_path,
125
132
  :clone,
126
133
  :dissoc,
127
134
  :eq_props,
128
135
  :has,
129
136
  :has_in,
130
137
  :keys,
131
- # :keys_in,
138
+ :lens,
139
+ :lens_index,
140
+ :lens_path,
141
+ :lens_prop,
132
142
  :merge,
133
143
  :omit,
144
+ :over,
134
145
  :path,
135
146
  :pick,
136
147
  :pick_all,
148
+ :pick_by,
137
149
  :project,
138
150
  :prop,
139
151
  :prop_or,
140
152
  :props,
153
+ :set,
141
154
  :to_pairs,
142
- # :to_pairs_in,
143
155
  :values,
144
- # :values_in,
156
+ :view,
145
157
  :where
146
158
 
147
159
  def_delegators Ramda::Relation,
@@ -156,7 +168,9 @@ module Ramda
156
168
  :lt,
157
169
  :lte,
158
170
  :max,
171
+ :max_by,
159
172
  :min,
173
+ :min_by,
160
174
  :path_eq,
161
175
  :prop_eq,
162
176
  :sort_by,
@@ -173,5 +187,6 @@ module Ramda
173
187
 
174
188
  def_delegators Ramda::Type,
175
189
  :is,
176
- :is_nil
190
+ :is_nil,
191
+ :type
177
192
  end
@@ -337,7 +337,7 @@ module Ramda
337
337
  # (((a, b, ..., n) -> o), (o -> p), ..., (x -> y), (y -> z)) -> ((a, b, ..., n) -> z)
338
338
  #
339
339
  curried_method(:pipe) do |*fns|
340
- ->(*args) { fns.reduce(args) { |memo, fn| [fn.call(*memo)] }.first }
340
+ ->(*args) { fns[1..-1].reduce(fns[0].call(*args)) { |memo, fn| fn.call(memo) } }
341
341
  end
342
342
 
343
343
  # Runs the given function with the supplied object, then returns the object.
@@ -349,6 +349,22 @@ module Ramda
349
349
  x
350
350
  end
351
351
 
352
+ # Takes a function fn, which takes a single array argument, and returns a
353
+ # function which:
354
+ #
355
+ # * takes any number of positional arguments;
356
+ # * passes these arguments to fn as an array; and
357
+ # * returns the result.
358
+ #
359
+ # In other words, R.unapply derives a variadic function from a function
360
+ # which takes an array. R.unapply is the inverse of R.apply.
361
+ #
362
+ # ([*...] -> a) -> (*... -> a)
363
+ #
364
+ curried_method(:unapply) do |fn, x, *xs|
365
+ fn.call([x] + xs)
366
+ end
367
+
352
368
  # Wraps a function of any arity (including nullary) in a function that
353
369
  # accepts exactly 1 parameter. Any extraneous parameters will not be passed
354
370
  # to the supplied function.
@@ -0,0 +1,44 @@
1
+ module Ramda
2
+ module Internals
3
+ module Functors
4
+ # `const` is a functor that effectively ignores the function given to `map`.
5
+ class Const
6
+ attr_reader :value
7
+
8
+ def self.of(x)
9
+ new(x)
10
+ end
11
+
12
+ def map(*)
13
+ Const.of(@value)
14
+ end
15
+
16
+ private
17
+
18
+ def initialize(value)
19
+ @value = value
20
+ end
21
+ end
22
+
23
+ # `Identity` is a functor that holds a single value, where `map` simply
24
+ # transforms the held value with the provided function.
25
+ class Identity
26
+ attr_reader :value
27
+
28
+ def self.of(x)
29
+ new(x)
30
+ end
31
+
32
+ def map(f)
33
+ Identity.of(f.call(@value))
34
+ end
35
+
36
+ private
37
+
38
+ def initialize(value)
39
+ @value = value
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -258,6 +258,8 @@ module Ramda
258
258
  # Ramda provides suitable map implementations for Array and Object,
259
259
  # so this function may be applied to [1, 2, 3] or {x: 1, y: 2, z: 3}.
260
260
  #
261
+ # Also treats functions as functors and will compose them together.
262
+ #
261
263
  # Functor f => (a -> b) -> f a -> f b
262
264
  #
263
265
  curried_method(:map) do |f, functor|
@@ -267,7 +269,11 @@ module Ramda
267
269
  when ::Array
268
270
  functor.map(&f)
269
271
  else
270
- type_error(functor, :map)
272
+ if functor.respond_to?(:map)
273
+ functor.map(f)
274
+ else
275
+ type_error(functor, :map)
276
+ end
271
277
  end
272
278
  end
273
279
 
@@ -281,8 +287,8 @@ module Ramda
281
287
  case xs
282
288
  when ::String
283
289
  xs[index] || ''
284
- when ::Array
285
- xs[index]
290
+ when ::Array, ::Hash
291
+ xs.fetch(index, nil)
286
292
  else
287
293
  type_error(xs, :nth)
288
294
  end
@@ -475,6 +481,15 @@ module Ramda
475
481
  Ramda.chain(Ramda.identity, xs)
476
482
  end
477
483
 
484
+ # Returns a new copy of the array with the element at the provided
485
+ # index replaced with the given value.
486
+ #
487
+ # Number -> a -> [a] -> [a]
488
+ #
489
+ curried_method(:update) do |idx, x, xs|
490
+ xs.dup.tap { |a| a[idx] = x }
491
+ end
492
+
478
493
  # Creates a new list out of the two supplied by creating each possible pair
479
494
  # from the lists.
480
495
  #
@@ -59,6 +59,12 @@ module Ramda
59
59
  a * b
60
60
  end
61
61
 
62
+ # Negates its argument.
63
+ #
64
+ # Number -> Number
65
+ #
66
+ curried_method(:negate, &:-@)
67
+
62
68
  # Multiplies together all the elements of a list.
63
69
  #
64
70
  # [Number] -> Number
@@ -1,10 +1,14 @@
1
1
  require_relative 'internal/curried_method'
2
+ require_relative 'internal/functors'
2
3
 
3
4
  module Ramda
4
5
  # Math functions
6
+ # rubocop:disable Metrics/ModuleLength
5
7
  module Object
6
8
  extend ::Ramda::Internal::CurriedMethod
7
9
 
10
+ Functors = ::Ramda::Internals::Functors
11
+
8
12
  # Makes a shallow clone of an object, setting or overriding the specified
9
13
  # property with the given value. Note that this copies and flattens
10
14
  # prototype properties onto the new object as well. All non-primitive
@@ -16,6 +20,32 @@ module Ramda
16
20
  obj.merge(key => val)
17
21
  end
18
22
 
23
+ # Makes a shallow clone of an object, setting or overriding the nodes
24
+ # required to create the given path, and placing the specific value at
25
+ # the tail end of that path. Note that this copies and flattens
26
+ # prototype properties onto the new object as well. All non-primitive
27
+ # properties are copied by reference.
28
+ #
29
+ # [Idx] -> a -> {a} -> {a}
30
+ # Idx = String | Int
31
+ #
32
+ curried_method(:assoc_path) do |path, val, obj|
33
+ if path.empty?
34
+ val
35
+ else
36
+ cloned = clone(obj)
37
+ path[0...-1].reduce(cloned) do |acc, k|
38
+ case acc[k]
39
+ when Hash, Array
40
+ acc[k]
41
+ else
42
+ acc[k] = k.is_a?(Integer) ? [] : {}
43
+ end
44
+ end[path[-1]] = val
45
+ cloned
46
+ end
47
+ end
48
+
19
49
  # Creates a deep copy of the value which may contain (nested)
20
50
  # Arrays and Objects, Numbers, Strings, Booleans and Dates.
21
51
  # Functions are assigned by reference rather than copied
@@ -24,8 +54,14 @@ module Ramda
24
54
  #
25
55
  curried_method(:clone) do |obj|
26
56
  case obj
57
+ when Hash
58
+ obj.each_with_object(obj.dup) do |(key, value), acc|
59
+ acc[clone(key)] = clone(value)
60
+ end
27
61
  when Array
28
- obj.dup.map(&method(:clone))
62
+ obj.map(&clone)
63
+ when Symbol, Integer, NilClass, TrueClass, FalseClass
64
+ obj
29
65
  else
30
66
  obj.dup
31
67
  end
@@ -86,6 +122,51 @@ module Ramda
86
122
  .uniq
87
123
  end
88
124
 
125
+ # Returns a lens for the given getter and setter functions.
126
+ # The getter "gets" the value of the focus;
127
+ # the setter "sets" the value of the focus.
128
+ # The setter should not mutate the data structure.
129
+ #
130
+ # (s -> a) -> ((a, s) -> s) -> Lens s a
131
+ # Lens s a = Functor f => (a -> f a) -> s -> f s
132
+ #
133
+ curried_method(:lens) do |getter, setter|
134
+ curried_method_body(:lens, 2) do |to_functor_fn, target|
135
+ Ramda.map(
136
+ ->(focus) { setter.call(focus, target) },
137
+ to_functor_fn.call(getter.call(target))
138
+ )
139
+ end
140
+ end
141
+
142
+ # Returns a lens whose focus is the specified index.
143
+ #
144
+ # Number -> Lens s a
145
+ # Lens s a = Functor f => (a -> f a) -> s -> f s
146
+ #
147
+ curried_method(:lens_index) do |n|
148
+ lens(Ramda.nth(0), Ramda.update(n))
149
+ end
150
+
151
+ # Returns a lens whose focus is the specified path.
152
+ #
153
+ # [Idx] -> Lens s a
154
+ # Idx = String | Int
155
+ # Lens s a = Functor f => (a -> f a) -> s -> f s
156
+ #
157
+ curried_method(:lens_path) do |path|
158
+ lens(Ramda.path(path), Ramda.assoc_path(path))
159
+ end
160
+
161
+ # Returns a lens whose focus is the specified property.
162
+ #
163
+ # String -> Lens s a
164
+ # Lens s a = Functor f => (a -> f a) -> s -> f s
165
+ #
166
+ curried_method(:lens_prop) do |k|
167
+ lens(Ramda.prop(k), Ramda.assoc(k))
168
+ end
169
+
89
170
  # Create a new object with the own properties of the first object merged
90
171
  # with the own properties of the second object. If a key exists in both
91
172
  # objects, the value from the second object will be used.
@@ -101,18 +182,34 @@ module Ramda
101
182
  # [String] -> {String: *} -> {String: *}
102
183
  #
103
184
  curried_method(:omit) do |keys, obj|
104
- obj_copy = obj.dup
185
+ obj_copy = clone(obj)
105
186
  keys.each(&obj_copy.method(:delete))
106
187
  obj_copy
107
188
  end
108
189
 
190
+ # Returns the result of "setting" the portion of the given data
191
+ # structure focused by the given lens to the result of applying
192
+ # the given function to the focused value.
193
+ #
194
+ # Lens s a -> (a -> a) -> s -> s
195
+ # Lens s a = Functor f => (a -> f a) -> s -> f s
196
+ #
197
+ curried_method(:over) do |lens, f, x|
198
+ # The value returned by the getter function is first transformed with `f`,
199
+ # then set as the value of an `Identity`. This is then mapped over with the
200
+ # setter function of the lens.
201
+ lens
202
+ .call(->(y) { Functors::Identity.of(y).map(f) }, x)
203
+ .value
204
+ end
205
+
109
206
  # Retrieve the value at a given path.
110
207
  #
111
208
  # [Idx] -> {a} -> a | NilClass
112
209
  # Idx = String | Int
113
210
  #
114
211
  curried_method(:path) do |keys, obj|
115
- keys.reduce(obj) { |acc, key| acc.is_a?(Hash) ? acc.fetch(key, nil) : nil }
212
+ keys.reduce(obj) { |acc, key| acc.respond_to?(:fetch) ? acc.fetch(key, nil) : nil }
116
213
  end
117
214
 
118
215
  # Returns a partial copy of an object containing only the keys specified.
@@ -133,6 +230,15 @@ module Ramda
133
230
  Hash[keys.map { |k| [k, obj.key?(k) ? obj.fetch(k) : nil] }]
134
231
  end
135
232
 
233
+ # Returns a partial copy of an object containing only the keys that
234
+ # satisfy the supplied predicate.
235
+ #
236
+ # (v, k -> Boolean) -> {k: v} -> {k: v}
237
+ #
238
+ curried_method(:pick_by) do |fn, obj|
239
+ obj.select { |k, v| fn.call(v, k) }
240
+ end
241
+
136
242
  # Reasonable analog to SQL select statement.
137
243
  #
138
244
  # [k] -> [{k: v}] -> [{k: v}]
@@ -174,6 +280,16 @@ module Ramda
174
280
  keys.map(&obj.method(:[]))
175
281
  end
176
282
 
283
+ # Returns the result of "setting" the portion of the given data structure
284
+ # focused by the given lens to the given value.
285
+ #
286
+ # Lens s a -> a -> s -> s
287
+ # Lens s a = Functor f => (a -> f a) -> s -> f s
288
+ #
289
+ curried_method(:set) do |lens, v, x|
290
+ over(lens, Ramda.always(v), x)
291
+ end
292
+
177
293
  # Converts an object into an array of key, value arrays. Only the
178
294
  # object's own properties are used. Note that the order of the
179
295
  # output array is not guaranteed.
@@ -197,6 +313,21 @@ module Ramda
197
313
  keys_in(obj).map(&obj.method(:send))
198
314
  end
199
315
 
316
+ # Returns a "view" of the given data structure, determined
317
+ # by the given lens. The lens's focus determines which portion
318
+ # of the data structure is visible.
319
+ #
320
+ # Lens s a -> s -> a
321
+ # Lens s a = Functor f => (a -> f a) -> s -> f s
322
+ #
323
+ curried_method(:view) do |lens, x|
324
+ # Using `const` effectively ignores the setter function of the `lens`,
325
+ # leaving the value returned by the getter function unmodified.
326
+ lens
327
+ .call(Functors::Const.method(:of), x)
328
+ .value
329
+ end
330
+
200
331
  # Takes a spec object and a test object; returns true if the test satisfies
201
332
  # the spec. Each of the spec's own properties must be a predicate function.
202
333
  # Each predicate is applied to the value of the corresponding property of
@@ -111,6 +111,15 @@ module Ramda
111
111
  [a, b].max
112
112
  end
113
113
 
114
+ # Takes a function and two values, and returns whichever value produces
115
+ # the larger result when passed to the provided function.
116
+ #
117
+ # Ord b => (a -> b) -> a -> a -> a
118
+ #
119
+ curried_method(:max_by) do |fn, a, b|
120
+ [a, b].max_by(&fn)
121
+ end
122
+
114
123
  # Returns the smaller of its two arguments.
115
124
  #
116
125
  # Ord a => a -> a -> a
@@ -119,6 +128,15 @@ module Ramda
119
128
  [a, b].min
120
129
  end
121
130
 
131
+ # Takes a function and two values, and returns whichever value
132
+ # produces the smaller result when passed to the provided function.
133
+ #
134
+ # Ord b => (a -> b) -> a -> a -> a
135
+ #
136
+ curried_method(:min_by) do |fn, a, b|
137
+ [a, b].min_by(&fn)
138
+ end
139
+
122
140
  # Determines whether a nested path on an object has a specific value,
123
141
  # in R.equals terms. Most likely used to filter a list.
124
142
  #
@@ -19,5 +19,11 @@ module Ramda
19
19
  # * -> Boolean
20
20
  #
21
21
  curried_method(:is_nil, &:nil?)
22
+
23
+ # Gives a class of the (native) type of a value.
24
+ #
25
+ # (* -> {*}) -> String
26
+ #
27
+ curried_method(:type, &:class)
22
28
  end
23
29
  end
@@ -1,3 +1,3 @@
1
1
  module Ramda
2
- VERSION = '0.7.0'.freeze
2
+ VERSION = '0.8.0'.freeze
3
3
  end
@@ -392,6 +392,13 @@ describe Ramda::Function do
392
392
  end
393
393
  end
394
394
 
395
+ context '#unapply' do
396
+ it 'from docs' do
397
+ stringify = ->(args) { args.to_s }
398
+ expect(r.unapply(stringify).call(1, 2, 3)).to eq('[1, 2, 3]')
399
+ end
400
+ end
401
+
395
402
  context '#unary' do
396
403
  it 'from docs' do
397
404
  takes_two_args = ->(a, b) { [a, b] }
@@ -309,15 +309,23 @@ describe Ramda::List do
309
309
  end
310
310
 
311
311
  context '#nth' do
312
- it 'from docs' do
312
+ it 'with array' do
313
313
  list = ['foo', 'bar', 'baz', 'quux']
314
314
  expect(r.nth(1, list)).to eq('bar')
315
315
  expect(r.nth(-1, list)).to eq('quux')
316
316
  expect(r.nth(-99, list)).to be_nil
317
+ end
317
318
 
319
+ it 'with string' do
318
320
  expect(r.nth(2, 'abc')).to eq('c')
319
321
  expect(r.nth(3, 'abc')).to eq('')
320
322
  end
323
+
324
+ it 'with hash' do
325
+ list = { a: 123 }
326
+ expect(r.nth(:a, list)).to eq(123)
327
+ expect(r.nth(:b, list)).to be_nil
328
+ end
321
329
  end
322
330
 
323
331
  context '#partition' do
@@ -526,6 +534,19 @@ describe Ramda::List do
526
534
  end
527
535
  end
528
536
 
537
+ context '#update' do
538
+ it 'without mutation' do
539
+ original = [0, 1, 2]
540
+ updated = r.update(1, 11, original)
541
+ expect(updated).to eq([0, 11, 2])
542
+ expect(original).to eq([0, 1, 2])
543
+ end
544
+
545
+ it 'is curried' do
546
+ expect(r.update(1).call(11).call([0, 1, 2])).to eq([0, 11, 2])
547
+ end
548
+ end
549
+
529
550
  context '#xprod' do
530
551
  it 'from docs' do
531
552
  expect(r.xprod([1, 2], ['a', 'b']))
@@ -84,6 +84,12 @@ describe Ramda::Math do
84
84
  end
85
85
  end
86
86
 
87
+ context '#negate' do
88
+ it 'from docs' do
89
+ expect(R.negate(42)).to eq(-42)
90
+ end
91
+ end
92
+
87
93
  context '#product' do
88
94
  it 'from docs' do
89
95
  expect(r.product([2, 4, 6, 8, 100, 1])).to be(38_400)
@@ -9,6 +9,23 @@ describe Ramda::Object do
9
9
  end
10
10
  end
11
11
 
12
+ context '#assoc_path' do
13
+ it 'from docs' do
14
+ expect(r.assoc_path([:a, :b, :c], 42, a: { b: { c: 0 } })).to eq(a: { b: { c: 42 } })
15
+ expect(r.assoc_path([:a, :b, :c], 42, a: 5)).to eq(a: { b: { c: 42 } })
16
+ expect(r.assoc_path([:a, :b, :c], 42, a: 5, d: 10)).to eq(a: { b: { c: 42 } }, d: 10)
17
+ end
18
+
19
+ it 'with object + array' do
20
+ obj = { x: [{ y: 2, z: 3 }, { y: 4, z: 5 }] }
21
+ expect(r.assoc_path([:x, 0, :y], 1, obj)).to eq(x: [{ y: 1, z: 3 }, { y: 4, z: 5 }])
22
+ end
23
+
24
+ it 'empty path replaces the the whole object' do
25
+ expect(r.assoc_path([], 3, a: 1, b: 2)).to eq(3)
26
+ end
27
+ end
28
+
12
29
  context '#clone' do
13
30
  it 'from docs' do
14
31
  objects = [{}, {}, {}]
@@ -16,6 +33,31 @@ describe Ramda::Object do
16
33
  expect(objects).not_to be(objects_clone)
17
34
  expect(objects[0]).not_to be(objects_clone[0])
18
35
  end
36
+
37
+ it 'nested arrays' do
38
+ obj = [1, [2, 2, [3, 3]]]
39
+
40
+ cloned = r.clone(obj)
41
+ cloned[1][2][0] = 100
42
+
43
+ expect(cloned).not_to eq(obj)
44
+ path = Ramda.path([1, 2])
45
+ expect(path.call(obj)).to eq([3, 3])
46
+ expect(path.call(cloned)).to eq([100, 3])
47
+ end
48
+
49
+ it 'nested objects' do
50
+ obj = { a: { b: { c: 10 } } }
51
+
52
+ cloned = r.clone(obj)
53
+ cloned[:a][:b][:c] = 100
54
+
55
+ expect(cloned).not_to eq(obj)
56
+
57
+ path = Ramda.path([:a, :b])
58
+ expect(path.call(obj)).to eq(c: 10)
59
+ expect(path.call(cloned)).to eq(c: 100)
60
+ end
19
61
  end
20
62
 
21
63
  context '#dissoc' do
@@ -26,7 +68,7 @@ describe Ramda::Object do
26
68
 
27
69
  context '#has' do
28
70
  it 'from docs' do
29
- has_name = R.has(:name)
71
+ has_name = r.has(:name)
30
72
  expect(has_name.call(name: 'alice')).to be_truthy
31
73
  expect(has_name.call(name: 'bob')).to be_truthy
32
74
  expect(has_name.call({})).to be_falsey
@@ -34,7 +76,7 @@ describe Ramda::Object do
34
76
 
35
77
  it 'with placeholder' do
36
78
  point = { x: 0, y: 0 }
37
- point_has = R.has(R.__, point)
79
+ point_has = r.has(R.__, point)
38
80
  expect(point_has.call(:x)).to be_truthy
39
81
  expect(point_has.call(:y)).to be_truthy
40
82
  expect(point_has.call(:z)).to be_falsey
@@ -87,6 +129,124 @@ describe Ramda::Object do
87
129
  end
88
130
  end
89
131
 
132
+ context '#lens' do
133
+ def x_lens
134
+ r.lens(R.prop(:x), R.assoc(:x))
135
+ end
136
+
137
+ it 'with view' do
138
+ expect(R.view(x_lens, x: 1, y: 2)).to eq(1)
139
+ end
140
+
141
+ it 'with set' do
142
+ expect(R.set(x_lens, 4, x: 1, y: 2)).to eq(x: 4, y: 2)
143
+ end
144
+
145
+ it 'with over' do
146
+ expect(R.over(x_lens, R.negate, x: 1, y: 2)).to eq(x: -1, y: 2)
147
+ end
148
+ end
149
+
150
+ context '#lens_index' do
151
+ it 'from docs' do
152
+ head_lens = r.lens_index(0)
153
+
154
+ expect(R.view(head_lens, ['a', 'b', 'c'])).to eq('a')
155
+ expect(R.set(head_lens, 'x', ['a', 'b', 'c'])).to eq(['x', 'b', 'c'])
156
+ expect(R.over(head_lens, R.to_upper, ['a', 'b', 'c'])).to eq(['A', 'b', 'c'])
157
+ end
158
+ end
159
+
160
+ context '#lens_path' do
161
+ it 'from docs' do
162
+ x_head_y_lens = r.lens_path([:x, 0, :y])
163
+
164
+ obj = { x: [{ y: 2, z: 3 }, { y: 4, z: 5 }] }
165
+
166
+ expect(R.view(x_head_y_lens, obj)).to eq(2)
167
+ expect(R.set(x_head_y_lens, 1, obj)).to eq(x: [{ y: 1, z: 3 }, { y: 4, z: 5 }])
168
+ expect(R.over(x_head_y_lens, R.negate, obj)).to eq(x: [{ y: -2, z: 3 }, { y: 4, z: 5 }])
169
+
170
+ expect(obj).to eq(x: [{ y: 2, z: 3 }, { y: 4, z: 5 }])
171
+ end
172
+ end
173
+
174
+ context '#lens_prop' do
175
+ it 'from docs' do
176
+ x_lens = r.lens_prop(:x)
177
+
178
+ expect(R.view(x_lens, x: 1, y: 2)).to eq(1)
179
+ expect(R.set(x_lens, 4, x: 1, y: 2)).to eq(x: 4, y: 2)
180
+ expect(R.over(x_lens, R.negate, x: 1, y: 2)).to eq(x: -1, y: 2)
181
+ end
182
+ end
183
+
184
+ context 'view, over, and set' do
185
+ let(:alice) do
186
+ {
187
+ name: 'Alice Jones',
188
+ address: ['22 Walnut St', 'San Francisco', 'CA'],
189
+ pets: { dog: 'joker', cat: 'batman' }
190
+ }
191
+ end
192
+ let(:head_lens) { R.lens_index(0) }
193
+
194
+ it 'may be applied to a lens created by `lens_path`' do
195
+ dog_lens = R.lens_path([:pets, :dog])
196
+ expect(r.view(dog_lens, alice)).to eq('joker')
197
+ end
198
+
199
+ it 'may be applied to a lens created by `lens_prop`' do
200
+ name_lens = R.lens(R.prop(:name), R.assoc(:name))
201
+
202
+ expect(r.view(name_lens, alice)).to eq('Alice Jones')
203
+
204
+ expect(r.over(name_lens, R.to_upper, alice)).to eq(
205
+ name: 'ALICE JONES',
206
+ address: ['22 Walnut St', 'San Francisco', 'CA'],
207
+ pets: { dog: 'joker', cat: 'batman' }
208
+ )
209
+
210
+ expect(r.set(name_lens, 'Alice Smith', alice)).to eq(
211
+ name: 'Alice Smith',
212
+ address: ['22 Walnut St', 'San Francisco', 'CA'],
213
+ pets: { dog: 'joker', cat: 'batman' }
214
+ )
215
+ end
216
+
217
+ it 'may be applied to a lens created by `lens_index`' do
218
+ expect(R.view(head_lens, alice.fetch(:address))).to eq('22 Walnut St')
219
+
220
+ expect(R.over(head_lens, R.to_upper, alice.fetch(:address)))
221
+ .to eq(['22 WALNUT ST', 'San Francisco', 'CA'])
222
+
223
+ expect(R.set(head_lens, '52 Crane Ave', alice.fetch(:address)))
224
+ .to eq(['52 Crane Ave', 'San Francisco', 'CA'])
225
+ end
226
+
227
+ xit 'may be applied to composed lenses' do
228
+ address_lens = R.lens_prop(:address)
229
+ street_lens = R.compose(address_lens, head_lens)
230
+ dog_lens = R.compose(R.lens_path([:pets]), R.lens_path([:dog]))
231
+
232
+ expect(R.view(dog_lens, alice)).to eq(R.view(R.lens_path([:pets, :dog]), alice))
233
+
234
+ expect(R.view(street_lens, alice)).to eq('22 Walnut St')
235
+
236
+ expect(R.over(street_lens, R.to_upper, alice)).to eq(
237
+ name: 'Alice Jones',
238
+ address: ['22 WALNUT ST', 'San Francisco', 'CA'],
239
+ pets: { dog: 'joker', cat: 'batman' }
240
+ )
241
+
242
+ expect(R.set(street_lens, '52 Crane Ave', alice)).to eq(
243
+ name: 'Alice Jones',
244
+ address: ['52 Crane Ave', 'San Francisco', 'CA'],
245
+ pets: { dog: 'joker', cat: 'batman' }
246
+ )
247
+ end
248
+ end
249
+
90
250
  context '#merge' do
91
251
  it 'from docs' do
92
252
  expect(r.merge({ name: 'fred', age: 10 }, age: 40))
@@ -114,6 +274,11 @@ describe Ramda::Object do
114
274
  expect(r.path([:a, :b], a: { b: 2 })).to eq(2)
115
275
  expect(r.path([:a, :b], c: { b: 2 })).to eq(nil)
116
276
  end
277
+
278
+ it 'with object + array' do
279
+ obj = { x: [{ y: 2, z: 3 }, { y: 4, z: 5 }] }
280
+ expect(r.path([:x, 0, :y], obj)).to eq(2)
281
+ end
117
282
  end
118
283
 
119
284
  context '#pick' do
@@ -130,6 +295,14 @@ describe Ramda::Object do
130
295
  end
131
296
  end
132
297
 
298
+ context '#pick_by' do
299
+ it 'from docs' do
300
+ is_upper_case = ->(_, key) { key.upcase == key }
301
+ expect(r.pick_by(is_upper_case, 'a' => 1, 'b' => 2, 'A' => 3, 'B' => 4))
302
+ .to eq('A' => 3, 'B' => 4)
303
+ end
304
+ end
305
+
133
306
  context '#project' do
134
307
  it 'from docs' do
135
308
  abby = { name: 'Abby', age: 7, hair: 'blond', grade: 2 }
@@ -122,6 +122,17 @@ describe Ramda::Relation do
122
122
  end
123
123
  end
124
124
 
125
+ context '#max_by' do
126
+ it 'from docs' do
127
+ square = ->(n) { n * n; }
128
+
129
+ expect(r.max_by(square, -3, 2)).to eq(-3)
130
+
131
+ expect(R.reduce(r.max_by(square), 0, [3, -5, 4, 1, -2])).to eq(-5)
132
+ expect(R.reduce(r.max_by(square), 0, [])).to eq(0)
133
+ end
134
+ end
135
+
125
136
  context '#min' do
126
137
  it 'from docs' do
127
138
  expect(r.min(789, 123)).to be(123)
@@ -129,6 +140,17 @@ describe Ramda::Relation do
129
140
  end
130
141
  end
131
142
 
143
+ context '#min_by' do
144
+ it 'from docs' do
145
+ square = ->(n) { n * n; }
146
+
147
+ expect(r.min_by(square, -3, 2)).to eq(2)
148
+
149
+ expect(R.reduce(r.min_by(square), 100, [3, -5, 4, 1, -2])).to eq(1)
150
+ expect(R.reduce(r.min_by(square), 0, [])).to eq(0)
151
+ end
152
+ end
153
+
132
154
  context '#prop_eq' do
133
155
  it 'from docs' do
134
156
  abby = { name: 'Abby', age: 7, hair: 'blond' }
@@ -23,4 +23,16 @@ describe Ramda::Type do
23
23
  expect(r.is_nil('')).to be_falsey
24
24
  end
25
25
  end
26
+
27
+ context '#type' do
28
+ it 'from docs' do
29
+ expect(r.type({})).to be(Hash)
30
+ expect(r.type(false)).to be(FalseClass)
31
+ expect(r.type('s')).to be(String)
32
+ expect(r.type(nil)).to be(NilClass)
33
+ expect(r.type([])).to be(Array)
34
+ expect(r.type(/[A-z]/)).to be(Regexp)
35
+ expect(r.type(-> {})).to be(Proc)
36
+ end
37
+ end
26
38
  end
@@ -25,6 +25,7 @@ describe Ramda do
25
25
  r(:append)
26
26
  r(:apply)
27
27
  r(:assoc)
28
+ r(:assoc_path)
28
29
  r(:binary)
29
30
  r(:bind)
30
31
  r(:chain)
@@ -82,6 +83,10 @@ describe Ramda do
82
83
  r(:last)
83
84
  r(:last_index_of)
84
85
  r(:length)
86
+ r(:lens)
87
+ r(:lens_index)
88
+ r(:lens_path)
89
+ r(:lens_prop)
85
90
  r(:lift)
86
91
  r(:lift_n)
87
92
  r(:lt)
@@ -89,23 +94,28 @@ describe Ramda do
89
94
  r(:map)
90
95
  r(:match)
91
96
  r(:max)
97
+ r(:max_by)
92
98
  r(:memoize)
93
99
  r(:merge)
94
100
  r(:min)
101
+ r(:min_by)
95
102
  r(:modulo)
96
103
  r(:multiply)
97
104
  r(:n_ary)
105
+ r(:negate)
98
106
  r(:not)
99
107
  r(:nth)
100
108
  r(:of)
101
109
  r(:omit)
102
110
  r(:once)
103
111
  r(:or)
112
+ r(:over)
104
113
  r(:partition)
105
114
  r(:path)
106
115
  r(:path_eq)
107
116
  r(:pick)
108
117
  r(:pick_all)
118
+ r(:pick_by)
109
119
  r(:pipe)
110
120
  r(:pluck)
111
121
  r(:prepend)
@@ -123,6 +133,7 @@ describe Ramda do
123
133
  r(:repeat)
124
134
  r(:replace)
125
135
  r(:reverse)
136
+ r(:set)
126
137
  r(:slice)
127
138
  r(:sort)
128
139
  r(:sort_by)
@@ -138,14 +149,18 @@ describe Ramda do
138
149
  r(:to_pairs)
139
150
  r(:to_upper)
140
151
  r(:trim)
152
+ r(:type)
153
+ r(:unapply)
141
154
  r(:unary)
142
155
  r(:union)
143
156
  r(:union_with)
144
157
  r(:uniq)
145
158
  r(:uniq_with)
146
159
  r(:unnest)
160
+ r(:update)
147
161
  r(:use_with)
148
162
  r(:values)
163
+ r(:view)
149
164
  r(:where)
150
165
  r(:xprod)
151
166
  r(:zip)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ramda-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vadim Lazebny
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-23 00:00:00.000000000 Z
11
+ date: 2017-06-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby version of Ramda Js library.
14
14
  email:
@@ -31,6 +31,7 @@ files:
31
31
  - lib/ramda/function.rb
32
32
  - lib/ramda/internal/curried_method.rb
33
33
  - lib/ramda/internal/function_with_arity.rb
34
+ - lib/ramda/internal/functors.rb
34
35
  - lib/ramda/list.rb
35
36
  - lib/ramda/logic.rb
36
37
  - lib/ramda/math.rb