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.
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