immutable-ruby 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/immutable/core_ext/struct.rb +9 -0
- data/lib/immutable/enumerable.rb +9 -0
- data/lib/immutable/hash.rb +104 -4
- data/lib/immutable/list.rb +13 -13
- data/lib/immutable/nested.rb +3 -0
- data/lib/immutable/vector.rb +21 -11
- data/lib/immutable/version.rb +1 -1
- data/spec/lib/immutable/hash/dig_spec.rb +34 -0
- data/spec/lib/immutable/hash/fetch_values_spec.rb +22 -0
- data/spec/lib/immutable/hash/put_spec.rb +9 -0
- data/spec/lib/immutable/hash/subset_spec.rb +42 -0
- data/spec/lib/immutable/hash/superset_spec.rb +42 -0
- data/spec/lib/immutable/hash/to_proc_spec.rb +39 -0
- data/spec/lib/immutable/hash/values_at_spec.rb +26 -6
- data/spec/lib/immutable/list/all_spec.rb +1 -1
- data/spec/lib/immutable/list/any_spec.rb +1 -1
- data/spec/lib/immutable/list/at_spec.rb +1 -1
- data/spec/lib/immutable/list/construction_spec.rb +1 -1
- data/spec/lib/immutable/list/count_spec.rb +1 -1
- data/spec/lib/immutable/list/each_slice_spec.rb +1 -1
- data/spec/lib/immutable/list/each_spec.rb +1 -1
- data/spec/lib/immutable/list/empty_spec.rb +1 -1
- data/spec/lib/immutable/list/eql_spec.rb +1 -1
- data/spec/lib/immutable/list/find_index_spec.rb +1 -1
- data/spec/lib/immutable/list/find_spec.rb +1 -1
- data/spec/lib/immutable/list/group_by_spec.rb +1 -1
- data/spec/lib/immutable/list/hash_spec.rb +1 -1
- data/spec/lib/immutable/list/include_spec.rb +1 -1
- data/spec/lib/immutable/list/index_spec.rb +6 -2
- data/spec/lib/immutable/list/indices_spec.rb +1 -1
- data/spec/lib/immutable/list/inspect_spec.rb +1 -1
- data/spec/lib/immutable/list/join_spec.rb +1 -1
- data/spec/lib/immutable/list/last_spec.rb +1 -1
- data/spec/lib/immutable/list/maximum_spec.rb +1 -1
- data/spec/lib/immutable/list/minimum_spec.rb +1 -1
- data/spec/lib/immutable/list/multithreading_spec.rb +4 -4
- data/spec/lib/immutable/list/none_spec.rb +1 -1
- data/spec/lib/immutable/list/one_spec.rb +1 -1
- data/spec/lib/immutable/list/product_spec.rb +1 -1
- data/spec/lib/immutable/list/reduce_spec.rb +1 -1
- data/spec/lib/immutable/list/reverse_spec.rb +1 -1
- data/spec/lib/immutable/list/size_spec.rb +1 -1
- data/spec/lib/immutable/list/sum_spec.rb +1 -1
- data/spec/lib/immutable/list/tail_spec.rb +1 -1
- data/spec/lib/immutable/list/to_a_spec.rb +1 -1
- data/spec/lib/immutable/list/to_ary_spec.rb +1 -1
- data/spec/lib/immutable/nested/construction_spec.rb +11 -5
- data/spec/lib/immutable/set/add_spec.rb +4 -2
- data/spec/lib/immutable/set/grep_spec.rb +10 -10
- data/spec/lib/immutable/set/grep_v_spec.rb +59 -0
- data/spec/lib/immutable/vector/dig_spec.rb +30 -0
- data/spec/spec_helper.rb +4 -0
- metadata +323 -306
@@ -0,0 +1,42 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "immutable/hash"
|
3
|
+
|
4
|
+
describe Immutable::Hash do
|
5
|
+
describe "#>=" do
|
6
|
+
[
|
7
|
+
[{}, {}, true],
|
8
|
+
[{"A" => 1}, {}, true],
|
9
|
+
[{}, {"A" => 1}, false],
|
10
|
+
[{"A" => 1}, {"A" => 1}, true],
|
11
|
+
[{"A" => 1}, {"A" => 2}, false],
|
12
|
+
[{"A" => 1, "B" => 2, "C" => 3}, {"B" => 2}, true],
|
13
|
+
[{"B" => 2}, {"A" => 1, "B" => 2, "C" => 3}, false],
|
14
|
+
[{"A" => 1, "B" => 2, "C" => 3}, {"B" => 0}, false],
|
15
|
+
].each do |a, b, expected|
|
16
|
+
describe "for #{a.inspect} and #{b.inspect}" do
|
17
|
+
it "returns #{expected}" do
|
18
|
+
expect(H[a] >= H[b]).to eq(expected)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#>" do
|
25
|
+
[
|
26
|
+
[{}, {}, false],
|
27
|
+
[{"A" => 1}, {}, true],
|
28
|
+
[{}, {"A" => 1}, false],
|
29
|
+
[{"A" => 1}, {"A" => 1}, false],
|
30
|
+
[{"A" => 1}, {"A" => 2}, false],
|
31
|
+
[{"A" => 1, "B" => 2, "C" => 3}, {"B" => 2}, true],
|
32
|
+
[{"B" => 2}, {"A" => 1, "B" => 2, "C" => 3}, false],
|
33
|
+
[{"A" => 1, "B" => 2, "C" => 3}, {"B" => 0}, false],
|
34
|
+
].each do |a, b, expected|
|
35
|
+
describe "for #{a.inspect} and #{b.inspect}" do
|
36
|
+
it "returns #{expected}" do
|
37
|
+
expect(H[a] > H[b]).to eq(expected)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "immutable/hash"
|
3
|
+
|
4
|
+
describe Immutable::Hash do
|
5
|
+
describe "#to_proc" do
|
6
|
+
context "on Hash without default proc" do
|
7
|
+
let(:hash) { H.new("A" => "aye") }
|
8
|
+
|
9
|
+
it "returns a Proc instance" do
|
10
|
+
hash.to_proc.should be_kind_of(Proc)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "returns a Proc that returns the value of an existing key" do
|
14
|
+
hash.to_proc.call("A").should == "aye"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns a Proc that returns nil for a missing key" do
|
18
|
+
hash.to_proc.call("B").should be_nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "on Hash with a default proc" do
|
23
|
+
let(:hash) { H.new("A" => "aye") { |key| "#{key}-VAL" } }
|
24
|
+
|
25
|
+
it "returns a Proc instance" do
|
26
|
+
hash.to_proc.should be_kind_of(Proc)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns a Proc that returns the value of an existing key" do
|
30
|
+
hash.to_proc.call("A").should == "aye"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "returns a Proc that returns the result of the hash's default proc for a missing key" do
|
34
|
+
hash.to_proc.call("B").should == "B-VAL"
|
35
|
+
hash.should == H.new("A" => "aye")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -2,12 +2,32 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Immutable::Hash do
|
4
4
|
describe "#values_at" do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
context "on Hash without default proc" do
|
6
|
+
let(:hash) { H[:a => 9, :b => 'a', :c => -10, :d => nil] }
|
7
|
+
|
8
|
+
it "returns an empty vector when no keys are given" do
|
9
|
+
hash.values_at.should be_kind_of(Immutable::Vector)
|
10
|
+
hash.values_at.should eql(V.empty)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "returns a vector of values for the given keys" do
|
14
|
+
hash.values_at(:a, :d, :b).should be_kind_of(Immutable::Vector)
|
15
|
+
hash.values_at(:a, :d, :b).should eql(V[9, nil, 'a'])
|
16
|
+
end
|
17
|
+
|
18
|
+
it "fills nil when keys are missing" do
|
19
|
+
hash.values_at(:x, :a, :y, :b).should be_kind_of(Immutable::Vector)
|
20
|
+
hash.values_at(:x, :a, :y, :b).should eql(V[nil, 9, nil, 'a'])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "on Hash with default proc" do
|
25
|
+
let(:hash) { Immutable::Hash.new(:a => 9) { |key| "#{key}-VAL" } }
|
26
|
+
|
27
|
+
it "fills the result of the default proc when keys are missing" do
|
28
|
+
hash.values_at(:x, :a, :y).should be_kind_of(Immutable::Vector)
|
29
|
+
hash.values_at(:x, :a, :y).should eql(V['x-VAL', 9, 'y-VAL'])
|
30
|
+
end
|
11
31
|
end
|
12
32
|
end
|
13
33
|
end
|
@@ -3,7 +3,7 @@ require "spec_helper"
|
|
3
3
|
describe Immutable::List do
|
4
4
|
describe "#all?" do
|
5
5
|
context "on a really big list" do
|
6
|
-
let(:list) {
|
6
|
+
let(:list) { BigList }
|
7
7
|
|
8
8
|
it "doesn't run out of stack" do
|
9
9
|
-> { list.all? }.should_not raise_error
|
@@ -3,7 +3,7 @@ require "spec_helper"
|
|
3
3
|
describe Immutable::List do
|
4
4
|
describe "#any?" do
|
5
5
|
context "on a really big list" do
|
6
|
-
let(:list) {
|
6
|
+
let(:list) { BigList }
|
7
7
|
|
8
8
|
it "doesn't run out of stack" do
|
9
9
|
-> { list.any? { false } }.should_not raise_error
|
@@ -3,7 +3,7 @@ require "spec_helper"
|
|
3
3
|
describe Immutable::List do
|
4
4
|
describe "#at" do
|
5
5
|
context "on a really big list" do
|
6
|
-
let(:list) {
|
6
|
+
let(:list) { BigList }
|
7
7
|
|
8
8
|
it "doesn't run out of stack" do
|
9
9
|
-> { list.at(STACK_OVERFLOW_DEPTH) }.should_not raise_error
|
@@ -90,7 +90,7 @@ describe Immutable do
|
|
90
90
|
it "realizes values as they are needed" do
|
91
91
|
# this example shows that Lists are not as lazy as they could be
|
92
92
|
# if Lists were fully lazy, you would have to take(4) to hit the exception
|
93
|
-
expect { list.take(3).to_a }.to raise_exception
|
93
|
+
expect { list.take(3).to_a }.to raise_exception(RuntimeError)
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
@@ -5,7 +5,7 @@ describe Immutable::List do
|
|
5
5
|
describe "##{method}" do
|
6
6
|
context "on a really big list" do
|
7
7
|
it "doesn't run out of stack" do
|
8
|
-
-> {
|
8
|
+
-> { BigList.send(method, 1) { |item| } }.should_not raise_error
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -4,7 +4,7 @@ describe Immutable::List do
|
|
4
4
|
describe "#each" do
|
5
5
|
context "on a really big list" do
|
6
6
|
it "doesn't run out of stack" do
|
7
|
-
-> {
|
7
|
+
-> { BigList.each { |item| } }.should_not raise_error
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -4,7 +4,7 @@ describe Immutable::List do
|
|
4
4
|
describe "#empty?" do
|
5
5
|
context "on a really big list" do
|
6
6
|
it "doesn't run out of stack" do
|
7
|
-
-> {
|
7
|
+
-> { BigList.select(&:nil?).empty? }.should_not raise_error
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -4,7 +4,7 @@ describe Immutable::List do
|
|
4
4
|
describe "#eql?" do
|
5
5
|
context "on a really big list" do
|
6
6
|
it "doesn't run out of stack" do
|
7
|
-
-> {
|
7
|
+
-> { BigList.eql?(Immutable.interval(0, STACK_OVERFLOW_DEPTH)) }.should_not raise_error
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -5,7 +5,7 @@ describe Immutable::List do
|
|
5
5
|
describe "##{method}" do
|
6
6
|
context "on a really big list" do
|
7
7
|
it "doesn't run out of stack" do
|
8
|
-
-> {
|
8
|
+
-> { BigList.send(method) { |item| false } }.should_not raise_error
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -5,7 +5,7 @@ describe Immutable::List do
|
|
5
5
|
describe "##{method}" do
|
6
6
|
context "on a really big list" do
|
7
7
|
it "doesn't run out of stack" do
|
8
|
-
-> {
|
8
|
+
-> { BigList.send(method) { false } }.should_not raise_error
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -5,7 +5,7 @@ describe Immutable::List do
|
|
5
5
|
describe "##{method}" do
|
6
6
|
context "on a really big list" do
|
7
7
|
it "doesn't run out of stack" do
|
8
|
-
-> {
|
8
|
+
-> { BigList.send(method) }.should_not raise_error
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -5,7 +5,7 @@ describe Immutable::List do
|
|
5
5
|
describe "##{method}" do
|
6
6
|
context "on a really big list" do
|
7
7
|
it "doesn't run out of stack" do
|
8
|
-
-> {
|
8
|
+
-> { BigList.send(method, nil) }.should_not raise_error
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -4,7 +4,7 @@ describe Immutable::List do
|
|
4
4
|
describe "#index" do
|
5
5
|
context "on a really big list" do
|
6
6
|
it "doesn't run out of stack" do
|
7
|
-
-> {
|
7
|
+
-> { BigList.index(nil) }.should_not raise_error
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -25,7 +25,11 @@ describe Immutable::List do
|
|
25
25
|
].each do |values, item, expected|
|
26
26
|
context "looking for #{item.inspect} in #{values.inspect}" do
|
27
27
|
it "returns #{expected.inspect}" do
|
28
|
-
|
28
|
+
if RUBY_ENGINE == 'jruby' && RUBY_VERSION <= '2.2.2' && values[0].is_a?(Fixnum) && item.is_a?(Float)
|
29
|
+
skip "On JRuby, Enumerable#find_index doesn't test equality properly"
|
30
|
+
else
|
31
|
+
L[*values].index(item).should == expected
|
32
|
+
end
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
@@ -11,7 +11,7 @@ describe Immutable::List do
|
|
11
11
|
|
12
12
|
context "on a large list which doesn't contain desired item" do
|
13
13
|
it "doesn't blow the stack" do
|
14
|
-
-> {
|
14
|
+
-> { BigList.indices { |x| x < 0 }.size }.should_not raise_error
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -4,7 +4,7 @@ describe Immutable::List do
|
|
4
4
|
describe "#inspect" do
|
5
5
|
context "on a really big list" do
|
6
6
|
it "doesn't run out of stack" do
|
7
|
-
-> {
|
7
|
+
-> { BigList.inspect }.should_not raise_error
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -3,8 +3,8 @@ require "concurrent/atomics"
|
|
3
3
|
|
4
4
|
describe Immutable::List do
|
5
5
|
it "ensures each node of a lazy list will only be realized on ONE thread, even when accessed by multiple threads" do
|
6
|
-
counter = Concurrent::
|
7
|
-
list = (1..10000).to_list.map { |x| counter.
|
6
|
+
counter = Concurrent::Atom.new(0)
|
7
|
+
list = (1..10000).to_list.map { |x| counter.swap { |count| count + 1 }; x * 2 }
|
8
8
|
|
9
9
|
threads = 10.times.collect do
|
10
10
|
Thread.new do
|
@@ -14,7 +14,7 @@ describe Immutable::List do
|
|
14
14
|
end
|
15
15
|
threads.each(&:join)
|
16
16
|
|
17
|
-
counter.
|
17
|
+
counter.value.should == 10000
|
18
18
|
list.sum.should == 100010000
|
19
19
|
end
|
20
20
|
|
@@ -44,4 +44,4 @@ describe Immutable::List do
|
|
44
44
|
elapsed = Time.now - start
|
45
45
|
elapsed.should_not > 0.3
|
46
46
|
end
|
47
|
-
end
|
47
|
+
end
|
@@ -4,7 +4,7 @@ describe Immutable::List do
|
|
4
4
|
describe "#none?" do
|
5
5
|
context "on a really big list" do
|
6
6
|
it "doesn't run out of stack" do
|
7
|
-
-> {
|
7
|
+
-> { BigList.none? { false } }.should_not raise_error
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -4,7 +4,7 @@ describe Immutable::List do
|
|
4
4
|
describe "#one?" do
|
5
5
|
context "on a really big list" do
|
6
6
|
it "doesn't run out of stack" do
|
7
|
-
-> {
|
7
|
+
-> { BigList.one? { false } }.should_not raise_error
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -4,7 +4,7 @@ describe Immutable::List do
|
|
4
4
|
describe "#product" do
|
5
5
|
context "on a really big list" do
|
6
6
|
it "doesn't run out of stack" do
|
7
|
-
-> {
|
7
|
+
-> { BigList.product }.should_not raise_error
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -5,7 +5,7 @@ describe Immutable::List do
|
|
5
5
|
describe "##{method}" do
|
6
6
|
context "on a really big list" do
|
7
7
|
it "doesn't run out of stack" do
|
8
|
-
-> {
|
8
|
+
-> { BigList.send(method, &:+) }.should_not raise_error
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -4,7 +4,7 @@ describe Immutable::List do
|
|
4
4
|
describe "#reverse" do
|
5
5
|
context "on a really big list" do
|
6
6
|
it "doesn't run out of stack" do
|
7
|
-
-> {
|
7
|
+
-> { BigList.reverse }.should_not raise_error
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -5,7 +5,7 @@ describe Immutable::List do
|
|
5
5
|
describe "##{method}" do
|
6
6
|
context "on a really big list" do
|
7
7
|
it "doesn't run out of stack" do
|
8
|
-
-> {
|
8
|
+
-> { BigList.size }.should_not raise_error
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -4,7 +4,7 @@ describe Immutable::List do
|
|
4
4
|
describe "#tail" do
|
5
5
|
context "on a really big list" do
|
6
6
|
it "doesn't run out of stack" do
|
7
|
-
-> {
|
7
|
+
-> { BigList.select(&:nil?).tail }.should_not raise_error
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|