immutable-ruby 0.0.1 → 0.0.2

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/immutable/core_ext/struct.rb +9 -0
  3. data/lib/immutable/enumerable.rb +9 -0
  4. data/lib/immutable/hash.rb +104 -4
  5. data/lib/immutable/list.rb +13 -13
  6. data/lib/immutable/nested.rb +3 -0
  7. data/lib/immutable/vector.rb +21 -11
  8. data/lib/immutable/version.rb +1 -1
  9. data/spec/lib/immutable/hash/dig_spec.rb +34 -0
  10. data/spec/lib/immutable/hash/fetch_values_spec.rb +22 -0
  11. data/spec/lib/immutable/hash/put_spec.rb +9 -0
  12. data/spec/lib/immutable/hash/subset_spec.rb +42 -0
  13. data/spec/lib/immutable/hash/superset_spec.rb +42 -0
  14. data/spec/lib/immutable/hash/to_proc_spec.rb +39 -0
  15. data/spec/lib/immutable/hash/values_at_spec.rb +26 -6
  16. data/spec/lib/immutable/list/all_spec.rb +1 -1
  17. data/spec/lib/immutable/list/any_spec.rb +1 -1
  18. data/spec/lib/immutable/list/at_spec.rb +1 -1
  19. data/spec/lib/immutable/list/construction_spec.rb +1 -1
  20. data/spec/lib/immutable/list/count_spec.rb +1 -1
  21. data/spec/lib/immutable/list/each_slice_spec.rb +1 -1
  22. data/spec/lib/immutable/list/each_spec.rb +1 -1
  23. data/spec/lib/immutable/list/empty_spec.rb +1 -1
  24. data/spec/lib/immutable/list/eql_spec.rb +1 -1
  25. data/spec/lib/immutable/list/find_index_spec.rb +1 -1
  26. data/spec/lib/immutable/list/find_spec.rb +1 -1
  27. data/spec/lib/immutable/list/group_by_spec.rb +1 -1
  28. data/spec/lib/immutable/list/hash_spec.rb +1 -1
  29. data/spec/lib/immutable/list/include_spec.rb +1 -1
  30. data/spec/lib/immutable/list/index_spec.rb +6 -2
  31. data/spec/lib/immutable/list/indices_spec.rb +1 -1
  32. data/spec/lib/immutable/list/inspect_spec.rb +1 -1
  33. data/spec/lib/immutable/list/join_spec.rb +1 -1
  34. data/spec/lib/immutable/list/last_spec.rb +1 -1
  35. data/spec/lib/immutable/list/maximum_spec.rb +1 -1
  36. data/spec/lib/immutable/list/minimum_spec.rb +1 -1
  37. data/spec/lib/immutable/list/multithreading_spec.rb +4 -4
  38. data/spec/lib/immutable/list/none_spec.rb +1 -1
  39. data/spec/lib/immutable/list/one_spec.rb +1 -1
  40. data/spec/lib/immutable/list/product_spec.rb +1 -1
  41. data/spec/lib/immutable/list/reduce_spec.rb +1 -1
  42. data/spec/lib/immutable/list/reverse_spec.rb +1 -1
  43. data/spec/lib/immutable/list/size_spec.rb +1 -1
  44. data/spec/lib/immutable/list/sum_spec.rb +1 -1
  45. data/spec/lib/immutable/list/tail_spec.rb +1 -1
  46. data/spec/lib/immutable/list/to_a_spec.rb +1 -1
  47. data/spec/lib/immutable/list/to_ary_spec.rb +1 -1
  48. data/spec/lib/immutable/nested/construction_spec.rb +11 -5
  49. data/spec/lib/immutable/set/add_spec.rb +4 -2
  50. data/spec/lib/immutable/set/grep_spec.rb +10 -10
  51. data/spec/lib/immutable/set/grep_v_spec.rb +59 -0
  52. data/spec/lib/immutable/vector/dig_spec.rb +30 -0
  53. data/spec/spec_helper.rb +4 -0
  54. 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
- it "returns a vector of values for the given keys" do
6
- h = H[:a => 9, :b => 'a', :c => -10, :d => nil]
7
- h.values_at.should be_kind_of(Immutable::Vector)
8
- h.values_at.should eql(V.empty)
9
- h.values_at(:a, :d, :b).should be_kind_of(Immutable::Vector)
10
- h.values_at(:a, :d, :b).should eql(V[9, nil, 'a'])
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) { Immutable.interval(0, STACK_OVERFLOW_DEPTH) }
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) { Immutable.interval(0, STACK_OVERFLOW_DEPTH) }
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) { Immutable.interval(0, STACK_OVERFLOW_DEPTH) }
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
 
@@ -4,7 +4,7 @@ describe Immutable::List do
4
4
  describe "#count" do
5
5
  context "on a really big list" do
6
6
  it "doesn't run out of stack" do
7
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).count }.should_not raise_error
7
+ -> { BigList.count }.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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).send(method, 1) { |item| } }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).each { |item| } }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).select(&:nil?).empty? }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).eql?(Immutable.interval(0, STACK_OVERFLOW_DEPTH)) }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).send(method) { |item| false } }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).send(method) { false } }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).send(method) }.should_not raise_error
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 "#hash" do
5
5
  context "on a really big list" do
6
6
  it "doesn't run out of stack" do
7
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).hash }.should_not raise_error
7
+ -> { BigList.hash }.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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).send(method, nil) }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).index(nil) }.should_not raise_error
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
- L[*values].index(item).should == expected
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).indices { |x| x < 0 }.size }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).inspect }.should_not raise_error
7
+ -> { BigList.inspect }.should_not raise_error
8
8
  end
9
9
  end
10
10
 
@@ -4,7 +4,7 @@ describe Immutable::List do
4
4
  describe "#join" do
5
5
  context "on a really big list" do
6
6
  it "doesn't run out of stack" do
7
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).join }.should_not raise_error
7
+ -> { BigList.join }.should_not raise_error
8
8
  end
9
9
  end
10
10
 
@@ -4,7 +4,7 @@ describe Immutable::List do
4
4
  describe "#last" do
5
5
  context "on a really big list" do
6
6
  it "doesn't run out of stack" do
7
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).last }.should_not raise_error
7
+ -> { BigList.last }.should_not raise_error
8
8
  end
9
9
  end
10
10
 
@@ -4,7 +4,7 @@ describe Immutable::List do
4
4
  describe "#max" do
5
5
  context "on a really big list" do
6
6
  it "doesn't run out of stack" do
7
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).max }.should_not raise_error
7
+ -> { BigList.max }.should_not raise_error
8
8
  end
9
9
  end
10
10
 
@@ -4,7 +4,7 @@ describe Immutable::List do
4
4
  describe "#min" do
5
5
  context "on a really big list" do
6
6
  it "doesn't run out of stack" do
7
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).min }.should_not raise_error
7
+ -> { BigList.min }.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::Atomic.new(0)
7
- list = (1..10000).to_list.map { |x| counter.update { |count| count + 1 }; x * 2 }
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.get.should == 10000
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).none? { false } }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).one? { false } }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).product }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).send(method, &:+) }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).reverse }.should_not raise_error
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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).size }.should_not raise_error
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 "#sum" do
5
5
  context "on a really big list" do
6
6
  it "doesn't run out of stack" do
7
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).sum }.should_not raise_error
7
+ -> { BigList.sum }.should_not raise_error
8
8
  end
9
9
  end
10
10
 
@@ -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
- -> { Immutable.interval(0, STACK_OVERFLOW_DEPTH).select(&:nil?).tail }.should_not raise_error
7
+ -> { BigList.select(&:nil?).tail }.should_not raise_error
8
8
  end
9
9
  end
10
10