ramda-ruby 0.1.0.alpha → 0.1.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: 00738383c28ec2a3917c0154c2cd68f8243435b9
4
- data.tar.gz: b10e359516a0af531fd0f8d0ed96a928bcb4cbef
3
+ metadata.gz: 92c254b35426d8cb7d3e26e8a20a65dd0194a795
4
+ data.tar.gz: 49381b27473b09231633674595c3893ef9105600
5
5
  SHA512:
6
- metadata.gz: 7b7018823bd8db0091106355b1d50262a1ce1deb6fc78ce0c5dbd6e4e2714c526a8991bf39547dde74f64d3ac6ae995c4b152ea541ffecc8f94d05a78d0508db
7
- data.tar.gz: 26cd80e631e8cbf847672612a2340a34447746548a3b6d20bb1b940f34efdd5c24a9759b24ab80691cf4df01f6549572b532e169529675e64377659db60eeba5
6
+ metadata.gz: b3bb80690881e350816705eb9d91b91d507d633ae395ee904f37acbf8e90cbf2c2d8a2575a7805fb0be8009c7fab069e05eb2aa373883a9d6d350c2a6ef3d7b3
7
+ data.tar.gz: b6c9c51bd4a2ff317673d28ce65f0e1f5e1e3f06d62362a48ae04d429819012a6747ca12f5b2477678b1f7e6ae0d1f5e49e1333a8069ff8373081bd418207091
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  Ramda Ruby
2
2
  =============
3
3
 
4
- This is ruby version of of Ramda library from (http://ramdajs.com)
5
-
4
+ This is a ruby version of [Ramda Js](http://ramdajs.com) library.
6
5
 
7
6
  [![Gem Version](https://badge.fury.io/rb/ramda-ruby.svg)](http://badge.fury.io/rb/ramda-ruby)
8
7
  [![Travis badge](https://travis-ci.org/lazebny/ramda-ruby.svg?branch=master)](https://travis-ci.org/lazebny/ramda-ruby)
@@ -34,18 +33,34 @@ Or install it yourself as:
34
33
  And then require:
35
34
 
36
35
  ```ruby
37
- reuire 'ramda'
36
+ require 'ramda'
38
37
  ```
39
38
 
39
+ ## Philosophy of [Ramda](http://ramdajs.com)
40
+
41
+ * Ramda emphasizes a purer functional style.
42
+ Immutability and side-effect free functions are at the heart of its design philosophy.
43
+ This can help you get the job done with simple, elegant code.
44
+
45
+ * Ramda functions are automatically curried.
46
+ This allows you to easily build up new functions from old ones simply by not supplying the final parameters.
47
+
48
+ * The parameters to Ramda functions are arranged to make it convenient for currying.
49
+ The data to be operated on is generally supplied last.
50
+
51
+
40
52
  ## Documentation
41
53
 
42
- This gem tries to follow the same versions as ramdajs has.
54
+ This gem tries to follow the same versions as Ramda Js.
55
+
56
+ Currently the gem doesn't have own documentation but it tries to follow specification from [Ramda Js](http://ramdajs.com/docs/):
57
+
58
+ * each release contains [functions](docs/FUNCTIONS.md) from the relevant Ramda Js release
59
+ * each release includes more functions which i found pretty useful
43
60
 
44
- [Implemeted Functions](docs/FUNCTIONS.md)
61
+ You could use [Ramda Js](http://ramdajs.com/docs/) as a source of documentation.
45
62
 
46
- Currently this project doesn't have own documentation but it tries to follow
47
- specification from http://ramdajs.com/docs/. You could use this resource as a
48
- source of documentation. Examples exist in spec directory.
63
+ Ruby scpecific examples can be found in [tests](spec/ramda).
49
64
 
50
65
  ## Usage
51
66
 
data/docs/FUNCTIONS.md CHANGED
@@ -6,6 +6,7 @@
6
6
  * any
7
7
  * any_pass
8
8
  * append
9
+ * assoc
9
10
  * clone
10
11
  * comparator
11
12
  * compose
@@ -18,6 +19,7 @@
18
19
  * dec
19
20
  * difference
20
21
  * difference_with
22
+ * dissoc
21
23
  * divide
22
24
  * drop
23
25
  * eq_by
data/lib/ramda.rb CHANGED
@@ -85,7 +85,9 @@ module Ramda
85
85
  :sum
86
86
 
87
87
  def_delegators Ramda::Object,
88
+ :assoc,
88
89
  :clone,
90
+ :dissoc,
89
91
  :eq_props,
90
92
  :keys,
91
93
  :merge,
data/lib/ramda/object.rb CHANGED
@@ -5,21 +5,40 @@ module Ramda
5
5
  module Object
6
6
  extend ::Ramda::Internal::CurriedMethod
7
7
 
8
+ # Makes a shallow clone of an object, setting or overriding the specified
9
+ # property with the given value. Note that this copies and flattens
10
+ # prototype properties onto the new object as well. All non-primitive
11
+ # properties are copied by reference.
12
+ #
13
+ # String -> a -> {k: v} -> {k: v}
14
+ #
15
+ curried_method(:assoc) do |key, val, obj|
16
+ obj.merge(key => val)
17
+ end
18
+
8
19
  # Creates a deep copy of the value which may contain (nested)
9
20
  # Arrays and Objects, Numbers, Strings, Booleans and Dates.
10
21
  # Functions are assigned by reference rather than copied
11
22
  #
12
23
  # {*} -> {*}
13
24
  #
14
- curried_method(:clone) do |object|
15
- case object
25
+ curried_method(:clone) do |obj|
26
+ case obj
16
27
  when Array
17
- object.dup.map(&method(:clone))
28
+ obj.dup.map(&method(:clone))
18
29
  else
19
- object.dup
30
+ obj.dup
20
31
  end
21
32
  end
22
33
 
34
+ # Returns a new object that does not contain a prop property.
35
+ #
36
+ # String -> {k: v} -> {k: v}
37
+ #
38
+ curried_method(:dissoc) do |prop, obj|
39
+ clone(obj).tap { |o| o.delete(prop) }
40
+ end
41
+
23
42
  # Reports whether two objects have the same value, in R.equals terms,
24
43
  # for the specified property. Useful as a curried predicate.
25
44
  #
data/lib/ramda/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ramda
2
- VERSION = '0.1.0.alpha'.freeze
2
+ VERSION = '0.1.0'.freeze
3
3
  end
@@ -0,0 +1,200 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ramda::Function do
4
+ let(:r) { described_class }
5
+
6
+ context '#always' do
7
+ it 'from docs' do
8
+ str = 'Tee'
9
+ expect(r.always(str).call).to be(str)
10
+ end
11
+
12
+ it 'is curried' do
13
+ str = 'Tee'
14
+ expect(r.always.call(str).call).to be(str)
15
+ end
16
+ end
17
+
18
+ context '#comparator' do
19
+ it 'from docs' do
20
+ sort_rule = r.comparator(->(a, b) { a < b })
21
+ numbers = [30, 25, 21]
22
+ expect(R.sort(sort_rule, numbers)).to eq([21, 25, 30])
23
+ end
24
+ end
25
+
26
+ context '#compose' do
27
+ it 'from docs' do
28
+ classy_greeting = lambda do |first_name, last_name|
29
+ "The name's #{last_name}, #{first_name} #{last_name}"
30
+ end
31
+ abs = ->(val) { val < 0 ? -1 * val : val }
32
+
33
+ expect(r.compose(R.to_upper, classy_greeting).call('James', 'Bond'))
34
+ .to eq("THE NAME'S BOND, JAMES BOND")
35
+
36
+ expect(r.compose(abs, R.add(1), R.multiply(2)).call(-4)).to be(7)
37
+ end
38
+ end
39
+
40
+ context '#construct' do
41
+ it 'from docs' do
42
+ array_builder = r.construct(Array)
43
+ expect(array_builder.call(2, 10)).to eq([10, 10])
44
+ end
45
+ end
46
+
47
+ context '#converge' do
48
+ it 'from docs' do
49
+ average = r.converge(R.divide, [R.sum, R.length])
50
+ expect(average.call([1, 2, 3, 4, 5, 6, 7])).to eq(4)
51
+
52
+ strange_concat = r.converge(R.concat, [R.to_upper, R.to_lower])
53
+ expect(strange_concat.call('Yodel')).to eq('YODELyodel')
54
+ end
55
+ end
56
+
57
+ context '#curry' do
58
+ it 'from docs' do
59
+ add_four_numbers = ->(a, b, c, d) { a + b + c + d }
60
+
61
+ curried_add_four_numbers = r.curry(add_four_numbers)
62
+ f = curried_add_four_numbers.call(1, 2)
63
+ g = f.call(3)
64
+ expect(g.call(4)).to be(10)
65
+ end
66
+
67
+ def test_method(a)
68
+ a
69
+ end
70
+
71
+ it 'can receive a method' do
72
+ expect(r.curry(method(:test_method)).call(100)).to eq(100)
73
+ end
74
+ end
75
+
76
+ context '#flip' do
77
+ def merge_tree
78
+ ->(a, b, c) { [a, b, c] }
79
+ end
80
+
81
+ it 'from docs' do
82
+ expect(merge_tree.call(1, 2, 3)).to eq([1, 2, 3])
83
+ expect(r.flip(merge_tree).call(1, 2, 3)).to eq([2, 1, 3])
84
+ end
85
+
86
+ it 'curried' do
87
+ expect(r.flip(merge_tree).call(1, 2).call(3)).to eq([2, 1, 3])
88
+ expect(r.flip(merge_tree).call(1).call(2).call(3)).to eq([2, 1, 3])
89
+ end
90
+ end
91
+
92
+ context '#identity' do
93
+ it 'from docs' do
94
+ expect(r.identity(1)).to be(1)
95
+ obj = {}
96
+ expect(r.identity(obj)).to be(obj)
97
+ end
98
+
99
+ it 'is curried' do
100
+ obj = {}
101
+ expect(r.identity.call(obj)).to be(obj)
102
+ end
103
+ end
104
+
105
+ context '#invoker' do
106
+ it 'from docs' do
107
+ slice_form = r.invoker(1, 'slice')
108
+ expect(slice_form.call(6, 'abcdefghijklm')).to eq('g')
109
+
110
+ slice_form6 = r.invoker(2, 'slice').call(6)
111
+ expect(slice_form6.call(8, 'abcdefghijklmnop')).to eq('ghijklmn')
112
+ end
113
+ end
114
+
115
+ context '#memoize' do
116
+ it 'from docs' do
117
+ count = 0
118
+
119
+ sum = r.memoize(lambda do |a, b, c|
120
+ count += 1
121
+ a + b + c
122
+ end)
123
+
124
+ expect(sum.call(10, 20, 30)).to be(60)
125
+ expect(sum.call(10, 20, 30)).to be(60)
126
+ expect(sum.call(10, 20, 30)).to be(60)
127
+
128
+ expect(count).to be(1)
129
+ end
130
+
131
+ it 'is curried' do
132
+ count = 0
133
+
134
+ sum = r.memoize(lambda do |a, b, c|
135
+ count += 1
136
+ a + b + c
137
+ end)
138
+
139
+ expect(sum.call(10).call(20).call(30)).to be(60)
140
+ expect(sum.call(10, 20).call(30)).to be(60)
141
+ expect(sum.call(10, 20, 30)).to be(60)
142
+
143
+ expect(count).to be(1)
144
+ end
145
+ end
146
+
147
+ context '#n_ary' do
148
+ it 'from docs' do
149
+ takes_two_args = ->(a, b) { [a, b] }
150
+
151
+ # expect(takes_two_args.arity).to be(2)
152
+ expect(takes_two_args.call(1, 2)).to eq([1, 2])
153
+
154
+ takes_one_arg = r.n_ary(1, takes_two_args)
155
+ # expect(takes_one_arg.arity).to be(1)
156
+ expect(takes_one_arg.call(1, 2)).to eq([1, nil])
157
+ end
158
+ end
159
+
160
+ context '#once' do
161
+ it 'from docs' do
162
+ add_one_once = r.once(->(x) { x + 1 })
163
+ expect(add_one_once.call(10)).to eq(11)
164
+ expect(add_one_once.call(add_one_once.call(50))).to eq(11)
165
+ end
166
+ end
167
+
168
+ context '#pipe' do
169
+ it 'from docs' do
170
+ classy_greeting = lambda do |first_name, last_name|
171
+ "The name's #{last_name}, #{first_name} #{last_name}"
172
+ end
173
+ abs = ->(val) { val < 0 ? -1 * val : val }
174
+
175
+ expect(r.pipe(classy_greeting, R.to_upper).call('James', 'Bond'))
176
+ .to eq("THE NAME'S BOND, JAMES BOND")
177
+
178
+ expect(r.pipe(R.multiply(2), R.add(1), abs).call(-4)).to be(7)
179
+ end
180
+ end
181
+
182
+ context '#tap' do
183
+ it 'from docs' do
184
+ say_x = instance_double(Proc)
185
+ expect(say_x).to receive(:call).with(100)
186
+ expect(r.tap(say_x, 100)).to be(100)
187
+ end
188
+ end
189
+
190
+ context '#use_with' do
191
+ it 'from docs' do
192
+ pow = ->(x, count) { Array.new(count, x).reduce(:*) }
193
+
194
+ expect(r.use_with(pow, [R.identity, R.identity]).call(3, 4)).to eq(81)
195
+ expect(r.use_with(pow, [R.identity, R.identity]).call(3).call(4)).to eq(81)
196
+ expect(r.use_with(pow, [R.dec, R.inc]).call(3, 4)).to eq(32)
197
+ expect(r.use_with(pow, [R.dec, R.inc]).call(3).call(4)).to eq(32)
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ramda::Internal::CurriedMethod do
4
+ let(:instance) { Class.new { extend Ramda::Internal::CurriedMethod } }
5
+
6
+ it '#curried_method' do
7
+ instance.curried_method(:sample_method) do |a, b, c|
8
+ a + b + c
9
+ end
10
+
11
+ expect(instance.sample_method.call(1).call(2).call(3)).to be(6)
12
+ expect(instance.sample_method(1).call(2).call(3)).to be(6)
13
+ expect(instance.sample_method(1, 2).call(3)).to be(6)
14
+ expect(instance.sample_method(1, 2, 3)).to be(6)
15
+ end
16
+ end
@@ -0,0 +1,399 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ramda::List do
4
+ let(:r) { described_class }
5
+
6
+ context '#all' do
7
+ it 'test' do
8
+ equals3 = R.equals(3)
9
+ expect(r.all(equals3, [3, 3, 3, 3])).to be_truthy
10
+ expect(r.all(equals3, [3, 3, 1, 3])).to be_falsey
11
+ end
12
+
13
+ it 'is curried' do
14
+ equals3 = R.equals(3)
15
+ expect(r.all(equals3).call([3, 3, 3])).to be_truthy
16
+ end
17
+ end
18
+
19
+ context '#any' do
20
+ it 'test' do
21
+ greater_than0 = R.lt(1)
22
+ greater_than2 = R.lt(2)
23
+
24
+ expect(r.any(greater_than0, [0, 1])).to be_falsey
25
+ expect(r.any(greater_than2, [2, 3])).to be_truthy
26
+ end
27
+
28
+ it 'is curried' do
29
+ greater_than0 = R.lt(1)
30
+
31
+ expect(r.any(greater_than0)[[0, 1]]).to be_falsey
32
+ end
33
+ end
34
+
35
+ context '#append' do
36
+ it 'from docs' do
37
+ expect(r.append('tests', ['write', 'more'])).to eq(['write', 'more', 'tests'])
38
+ expect(r.append('tests', [])).to eq(['tests'])
39
+ expect(r.append(['tests'], ['write', 'more'])).to eq(['write', 'more', ['tests']])
40
+ end
41
+
42
+ it 'is curried' do
43
+ expect(R.append(1).call([4, 3, 2])).to eq([4, 3, 2, 1])
44
+ end
45
+ end
46
+
47
+ context '#concat' do
48
+ it 'from docs' do
49
+ expect(r.concat('ABC', 'DEF')).to eq('ABCDEF')
50
+ expect(r.concat([4, 5, 6], [1, 2, 3])).to eql([4, 5, 6, 1, 2, 3])
51
+ expect(r.concat([], [])).to eql([])
52
+ end
53
+
54
+ it 'is curried' do
55
+ expect(r.concat('ABC').call('DEF')).to eq('ABCDEF')
56
+ end
57
+ end
58
+
59
+ context '#contains' do
60
+ it 'from docs' do
61
+ expect(r.contains(3, [1, 2, 3])).to be_truthy
62
+ expect(r.contains(4, [1, 2, 3])).to be_falsey
63
+ expect(r.contains({ name: 'Fred' }, [{ name: 'Fred' }])).to be_truthy
64
+ expect(r.contains([42], [[42]])).to be_truthy
65
+ end
66
+
67
+ it 'is curried' do
68
+ expect(r.contains(3).call([1, 2, 3]))
69
+ end
70
+ end
71
+
72
+ context '#drop' do
73
+ it 'from docs' do
74
+ expect(r.drop(1, ['foo', 'bar', 'baz'])).to eq(['bar', 'baz'])
75
+ expect(r.drop(2, ['foo', 'bar', 'baz'])).to eq(['baz'])
76
+ expect(r.drop(3, ['foo', 'bar', 'baz'])).to eq([])
77
+ expect(r.drop(4, ['foo', 'bar', 'baz'])).to eq([])
78
+ expect(r.drop(3, 'ramda')).to eq('da')
79
+ end
80
+
81
+ it 'is curried' do
82
+ expect(r.drop(3).call('ramda')).to eq('da')
83
+ end
84
+ end
85
+
86
+ context '#filter' do
87
+ def is_even
88
+ ->(n) { n.even? }
89
+ end
90
+
91
+ it 'from docs' do
92
+ expect(r.filter(is_even, [1, 2, 3, 4])).to eq([2, 4])
93
+ expect(r.filter(is_even, a: 1, b: 2, c: 3, d: 4)).to eq(b: 2, d: 4)
94
+ end
95
+
96
+ it 'is curried' do
97
+ expect(r.filter(is_even).call([1, 2, 3, 4])).to eq([2, 4])
98
+ end
99
+ end
100
+
101
+ context '#find' do
102
+ it 'from docs' do
103
+ list = [{ a: 1 }, { a: 2 }, { a: 3 }]
104
+
105
+ expect(r.find(R.prop_eq(:a, 2), list)).to eq(a: 2)
106
+ expect(r.find(R.prop_eq(:a, 4), list)).to be_nil
107
+ end
108
+
109
+ it 'is curried' do
110
+ list = [{ a: 1 }, { a: 2 }, { a: 3 }]
111
+
112
+ expect(r.find(R.prop_eq(:a, 2)).call(list)).to eq(a: 2)
113
+ end
114
+ end
115
+
116
+ context '#flatten' do
117
+ it 'from docs' do
118
+ expect(r.flatten([1, 2, [3, 4], 5, [6, [7, 8, [9, [10, 11], 12]]]]))
119
+ .to eq([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
120
+ end
121
+ end
122
+
123
+ context '#group_by' do
124
+ it 'from docs' do
125
+ by_grade = lambda do |student|
126
+ case student.fetch(:score)
127
+ when 0...65 then 'F'
128
+ when 0...70 then 'D'
129
+ when 0...80 then 'C'
130
+ when 0...90 then 'B'
131
+ else
132
+ 'A'
133
+ end
134
+ end
135
+ students = [
136
+ { name: 'Abby', score: 84 },
137
+ { name: 'Eddy', score: 58 },
138
+ { name: 'Jack', score: 69 }
139
+ ]
140
+ expect(r.group_by(by_grade, students)).to eq(
141
+ 'D' => [{ name: 'Jack', score: 69 }],
142
+ 'F' => [{ name: 'Eddy', score: 58 }],
143
+ 'B' => [{ name: 'Abby', score: 84 }]
144
+ )
145
+ end
146
+
147
+ it 'is curried' do
148
+ students = [
149
+ { name: 'Mike', age: 30 },
150
+ { name: 'Tom', age: 25 },
151
+ { name: 'Tom', age: 20 }
152
+ ]
153
+
154
+ group_by_name = r.group_by(->(a) { a.fetch(:name) })
155
+ expect(group_by_name.call(students)).to eq(
156
+ 'Tom' => [{ name: 'Tom', age: 25 }, { name: 'Tom', age: 20 }],
157
+ 'Mike' => [{ name: 'Mike', age: 30 }]
158
+ )
159
+ end
160
+ end
161
+
162
+ context '#head' do
163
+ it 'from docs' do
164
+ expect(r.head(['fi', 'fo', 'fum'])).to eq('fi')
165
+ expect(r.head([])).to be_nil
166
+ expect(r.head('abc')).to eq('a')
167
+ expect(r.head('')).to eq('')
168
+ end
169
+ end
170
+
171
+ context '#index_of' do
172
+ it 'from docs' do
173
+ expect(r.index_of(3, [1, 2, 3, 4])).to be(2)
174
+ expect(r.index_of(1, [1, 2, 3, 4])).to be(0)
175
+ expect(r.index_of(10, [1, 2, 3, 4])).to be(-1)
176
+ end
177
+ end
178
+
179
+ context '#join' do
180
+ it 'from docs' do
181
+ expect(r.join('|', [1, 2, 3])).to eq('1|2|3')
182
+ end
183
+
184
+ it 'is curried' do
185
+ spacer = r.join(' ')
186
+ expect(spacer.call(['a', 2, 3.4])).to eq('a 2 3.4')
187
+ end
188
+ end
189
+
190
+ context '#last_index_of' do
191
+ it 'from docs' do
192
+ expect(r.last_index_of(3, [-1, 3, 3, 0, 1, 2, 3, 4])).to be(6)
193
+ expect(r.last_index_of(10, [1, 2, 3, 4])).to be(-1)
194
+ end
195
+ end
196
+
197
+ context '#length' do
198
+ it 'from docs' do
199
+ expect(r.length([])).to eq(0)
200
+ expect(r.length([1, 2, 3])).to eq(3)
201
+ end
202
+ end
203
+
204
+ context '#map' do
205
+ it 'from docs' do
206
+ double_fn = ->(x) { x * 2 }
207
+
208
+ expect(r.map(double_fn, [1, 2, 3])).to eq([2, 4, 6])
209
+ expect(r.map(double_fn, x: 1, y: 2, z: 3)).to eq(x: 2, y: 4, z: 6)
210
+ end
211
+
212
+ it 'is curried' do
213
+ double_fn = ->(x) { x * 2 }
214
+
215
+ expect(r.map(double_fn).call([1, 2, 3])).to eq([2, 4, 6])
216
+ end
217
+ end
218
+
219
+ context '#nth' do
220
+ it 'from docs' do
221
+ list = ['foo', 'bar', 'baz', 'quux']
222
+ expect(r.nth(1, list)).to eq('bar')
223
+ expect(r.nth(-1, list)).to eq('quux')
224
+ expect(r.nth(-99, list)).to be_nil
225
+
226
+ expect(r.nth(2, 'abc')).to eq('c')
227
+ expect(r.nth(3, 'abc')).to eq('')
228
+ end
229
+ end
230
+
231
+ context '#pluck' do
232
+ it 'from docs' do
233
+ expect(r.pluck(:a).call([{ a: 1 }, { a: 2 }])).to eq([1, 2])
234
+ expect(r.pluck(0).call([[1, 2], [3, 4]])).to eq([1, 3])
235
+ end
236
+ end
237
+
238
+ context '#prepend' do
239
+ it 'from docs' do
240
+ expect(r.prepend('fee').call(['fi', 'fo', 'fum'])).to eq(['fee', 'fi', 'fo', 'fum'])
241
+ end
242
+ end
243
+
244
+ context '#range' do
245
+ it 'from docs' do
246
+ expect(r.range(1, 5)).to eq([1, 2, 3, 4])
247
+ expect(r.range(50, 53)).to eq([50, 51, 52])
248
+ end
249
+ end
250
+
251
+ context '#reduce' do
252
+ it 'from docs' do
253
+ # ((((0 - 1) - 2) - 3) - 4) = -10
254
+ expect(r.reduce(R.subtract, 0, [1, 2, 3, 4])).to be(-10)
255
+ end
256
+ end
257
+
258
+ context '#reduce_right' do
259
+ def avg
260
+ ->(a, b) { (a + b) / 2 }
261
+ end
262
+
263
+ it 'from docs' do
264
+ # (1 - (2 - (3 - (4 - 0)))))
265
+ expect(r.reduce_right(R.subtract, 0, [1, 2, 3, 4])).to be(-2)
266
+ end
267
+
268
+ it 'returns the accumulator for an empty array' do
269
+ expect(r.reduce_right(avg, 0, [])).to eq(0)
270
+ end
271
+
272
+ it 'is curried' do
273
+ something = r.reduce_right(avg, 54)
274
+ rcat = r.reduce_right(R.concat, '')
275
+ expect(something.call([12, 4, 10, 6])).to eq(12)
276
+ expect(rcat.call(['1', '2', '3', '4'])).to eq('1234')
277
+ end
278
+ end
279
+
280
+ context '#reverse' do
281
+ it 'from docs' do
282
+ expect(r.reverse([1, 2, 3])).to eq([3, 2, 1])
283
+ expect(r.reverse([1, 2])).to eq([2, 1])
284
+ expect(r.reverse([1])).to eq([1])
285
+ expect(r.reverse([])).to eq([])
286
+
287
+ expect(r.reverse('abc')).to eq('cba')
288
+ expect(r.reverse('ab')).to eq('ba')
289
+ expect(r.reverse('a')).to eq('a')
290
+ expect(r.reverse('')).to eq('')
291
+ end
292
+ end
293
+
294
+ context '#reject' do
295
+ it 'from docs' do
296
+ is_odd = ->(n) { n.odd? }
297
+
298
+ expect(r.reject(is_odd, [1, 2, 3, 4])).to eq([2, 4])
299
+ expect(r.reject(is_odd, a: 1, b: 2, c: 3, d: 4)).to eq(b: 2, d: 4)
300
+ end
301
+ end
302
+
303
+ context '#sort' do
304
+ it 'from docs' do
305
+ diff = ->(a, b) { a - b }
306
+ expect(r.sort(diff, [4, 2, 7, 5])).to eq([2, 4, 5, 7])
307
+ end
308
+ end
309
+
310
+ context '#tail' do
311
+ it 'from docs' do
312
+ expect(r.tail([1, 2, 3])).to eq([2, 3])
313
+ expect(r.tail([1, 2])).to eq([2])
314
+ expect(r.tail([1])).to eq([])
315
+ expect(r.tail([])).to eq([])
316
+
317
+ expect(r.tail('abc')).to eq('bc')
318
+ expect(r.tail('ab')).to eq('b')
319
+ expect(r.tail('a')).to eq('')
320
+ expect(r.tail('')).to eq('')
321
+ end
322
+ end
323
+
324
+ context '#take' do
325
+ it 'is curried' do
326
+ personnel = [
327
+ 'Dave Brubeck',
328
+ 'Paul Desmond',
329
+ 'Eugene Wright',
330
+ 'Joe Morello',
331
+ 'Gerry Mulligan',
332
+ 'Bob Bates',
333
+ 'Joe Dodge',
334
+ 'Ron Crotty'
335
+ ]
336
+
337
+ take_five = r.take(5)
338
+ expect(take_five.call(personnel)).to eq(
339
+ ['Dave Brubeck', 'Paul Desmond', 'Eugene Wright', 'Joe Morello', 'Gerry Mulligan']
340
+ )
341
+ end
342
+
343
+ it 'can operate on arrays' do
344
+ expect(r.take(10, [])).to eq([])
345
+ expect(r.take(4, ['foo', 'bar', 'baz'])).to eq(['foo', 'bar', 'baz'])
346
+ expect(r.take(3, ['foo', 'bar', 'baz'])).to eq(['foo', 'bar', 'baz'])
347
+ expect(r.take(2, ['foo', 'bar', 'baz'])).to eq(['foo', 'bar'])
348
+ expect(r.take(1, ['foo', 'bar', 'baz'])).to eq(['foo'])
349
+ expect(r.take(0, ['foo', 'bar', 'baz'])).to eq([])
350
+ end
351
+
352
+ it 'can operate on strings' do
353
+ expect(r.take(10, 'Ramda')).to eq('Ramda')
354
+ expect(r.take(3, 'Ramda')).to eq('Ram')
355
+ expect(r.take(2, 'Ramda')).to eq('Ra')
356
+ expect(r.take(1, 'Ramda')).to eq('R')
357
+ expect(r.take(0, 'Ramda')).to eq('')
358
+ end
359
+ end
360
+
361
+ context '#take_while' do
362
+ it 'from docs' do
363
+ is_not_four = ->(x) { x != 4 }
364
+
365
+ expect(r.take_while(is_not_four, [1, 2, 3, 4, 3, 2, 1])).to eq([1, 2, 3])
366
+ expect(r.take_while(is_not_four, [1, 2, 3])).to eq([1, 2, 3])
367
+ end
368
+ end
369
+
370
+ context '#uniq' do
371
+ it 'from docs' do
372
+ expect(r.uniq([1, 1, 2, 1])).to eq([1, 2])
373
+ expect(r.uniq([1, '1'])).to eq([1, '1'])
374
+ expect(r.uniq([[42], [42]])).to eq([[42]])
375
+ end
376
+ end
377
+
378
+ context '#xprod' do
379
+ it 'from docs' do
380
+ expect(r.xprod([1, 2], ['a', 'b']))
381
+ .to eq([[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']])
382
+ end
383
+ end
384
+
385
+ context '#zip' do
386
+ it 'from docs' do
387
+ expect(r.zip([1, 2, 3], ['a', 'b', 'c'])).to eq([[1, 'a'], [2, 'b'], [3, 'c']])
388
+ expect(r.zip([1, 2, 3], ['a', 'b', 'c', 'd'])).to eq([[1, 'a'], [2, 'b'], [3, 'c']])
389
+ end
390
+ end
391
+
392
+ context '#zip_with' do
393
+ it 'from docs' do
394
+ f = ->(x, y) { Ramda.join('', [x, y]) }
395
+
396
+ expect(r.zip_with(f, [1, 2, 3], ['a', 'b', 'c'])).to eq(['1a', '2b', '3c'])
397
+ end
398
+ end
399
+ end