keso 0.1.3 → 0.1.4
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.
- data/.bundle/config +2 -0
- data/{spec/spec.opts → .rspec} +0 -0
- data/Gemfile +4 -0
- data/Rakefile +3 -0
- data/VERSION +1 -1
- data/keso.gemspec +38 -33
- data/lib/values/immutable_set.rb +94 -49
- data/lib/values/relation.rb +8 -0
- data/spec/relation_spec.rb +6 -2
- data/spec/spec_helper.rb +3 -4
- data/timeit.rb +28 -0
- data/timeit/relation_bench.rb +125 -0
- metadata +27 -10
- data/.gitignore +0 -21
data/.bundle/config
ADDED
data/{spec/spec.opts → .rspec}
RENAMED
File without changes
|
data/Gemfile
ADDED
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
data/keso.gemspec
CHANGED
@@ -1,59 +1,61 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{keso}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Darwin"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-03-20}
|
13
13
|
s.description = %q{Cottage cheees with lots of relational theory. Or mabye not so much theory =(}
|
14
14
|
s.email = %q{darwin@markkonsulter.se}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
|
17
|
+
"README.rdoc"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
|
+
".bundle/config",
|
20
21
|
".document",
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
22
|
+
".rspec",
|
23
|
+
"Gemfile",
|
24
|
+
"LICENSE",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"keso.gemspec",
|
29
|
+
"lib/keso.rb",
|
30
|
+
"lib/realvar.rb",
|
31
|
+
"lib/values/attribute.rb",
|
32
|
+
"lib/values/heading.rb",
|
33
|
+
"lib/values/immutable_hash.rb",
|
34
|
+
"lib/values/immutable_set.rb",
|
35
|
+
"lib/values/relation.rb",
|
36
|
+
"lib/values/tuple.rb",
|
37
|
+
"spec/attribute_spec.rb",
|
38
|
+
"spec/heading_spec.rb",
|
39
|
+
"spec/immutable_hash_spec.rb",
|
40
|
+
"spec/immutable_set_spec.rb",
|
41
|
+
"spec/relation_spec.rb",
|
42
|
+
"spec/spec_helper.rb",
|
43
|
+
"spec/tuple_spec.rb",
|
44
|
+
"timeit.rb",
|
45
|
+
"timeit/relation_bench.rb"
|
43
46
|
]
|
44
47
|
s.homepage = %q{http://github.com/bjornblomqvist/keso}
|
45
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
46
48
|
s.require_paths = ["lib"]
|
47
49
|
s.rubygems_version = %q{1.3.7}
|
48
50
|
s.summary = %q{Cottage cheees with lots of relational theory}
|
49
51
|
s.test_files = [
|
50
52
|
"spec/attribute_spec.rb",
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
53
|
+
"spec/heading_spec.rb",
|
54
|
+
"spec/immutable_hash_spec.rb",
|
55
|
+
"spec/immutable_set_spec.rb",
|
56
|
+
"spec/relation_spec.rb",
|
57
|
+
"spec/spec_helper.rb",
|
58
|
+
"spec/tuple_spec.rb"
|
57
59
|
]
|
58
60
|
|
59
61
|
if s.respond_to? :specification_version then
|
@@ -61,11 +63,14 @@ Gem::Specification.new do |s|
|
|
61
63
|
s.specification_version = 3
|
62
64
|
|
63
65
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
66
|
+
s.add_runtime_dependency(%q<jeweler>, [">= 0"])
|
64
67
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
65
68
|
else
|
69
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
66
70
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
67
71
|
end
|
68
72
|
else
|
73
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
69
74
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
70
75
|
end
|
71
76
|
end
|
data/lib/values/immutable_set.rb
CHANGED
@@ -5,55 +5,44 @@ class ImmutableSet
|
|
5
5
|
|
6
6
|
def initialize(*args)
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
8
|
+
if args.first.is_a? ImmutableSet::SetChange
|
9
|
+
@set_change = args.first
|
10
|
+
else
|
11
|
+
@set = Set.new;
|
12
|
+
|
13
|
+
args.each do |value|
|
14
|
+
if value.is_a? ImmutableSet
|
15
|
+
@set.merge value.set
|
16
|
+
elsif value.is_a? Set
|
17
|
+
@set.merge value
|
18
|
+
elsif value.is_a? Array
|
19
|
+
@set.merge value
|
20
|
+
elsif not value.nil?
|
21
|
+
@set.add value
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
21
25
|
|
22
26
|
end
|
23
27
|
|
24
28
|
def size
|
25
|
-
|
29
|
+
self.set.size
|
26
30
|
end
|
27
31
|
|
28
32
|
alias :count :size
|
29
33
|
|
30
34
|
def each &block
|
31
|
-
|
35
|
+
self.set.to_a.each do |value|
|
32
36
|
block.call value
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
36
40
|
def add *values
|
37
|
-
|
38
|
-
new_set = @set.clone
|
39
|
-
|
40
|
-
values.each do |value|
|
41
|
-
if value.is_a? ImmutableSet
|
42
|
-
new_set.merge(value.to_a)
|
43
|
-
elsif value.is_a? Set
|
44
|
-
new_set.merge(value)
|
45
|
-
elsif value.is_a? Array
|
46
|
-
new_set.merge(value)
|
47
|
-
else
|
48
|
-
new_set.add(value)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
ImmutableSet.new(new_set)
|
41
|
+
ImmutableSet.new(SetChange.new(values,@set || @set_change.set,true,@set_change))
|
53
42
|
end
|
54
43
|
|
55
44
|
def hash
|
56
|
-
|
45
|
+
self.set.hash
|
57
46
|
end
|
58
47
|
|
59
48
|
def eql? other
|
@@ -71,32 +60,17 @@ class ImmutableSet
|
|
71
60
|
end
|
72
61
|
|
73
62
|
def delete *values
|
74
|
-
|
75
|
-
new_set = @set.clone
|
76
|
-
|
77
|
-
values.each do |value|
|
78
|
-
if value.is_a? ImmutableSet
|
79
|
-
new_set.subtract(value.to_a)
|
80
|
-
elsif value.is_a? Set
|
81
|
-
new_set.subtract(value)
|
82
|
-
elsif value.is_a? Array
|
83
|
-
new_set.subtract(value)
|
84
|
-
else
|
85
|
-
new_set.delete(value)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
ImmutableSet.new(new_set)
|
63
|
+
ImmutableSet.new(SetChange.new(values,@set || @set_change.set,false,@set_change))
|
90
64
|
end
|
91
65
|
|
92
66
|
alias :remove :delete
|
93
67
|
|
94
68
|
def to_a
|
95
|
-
|
69
|
+
self.set.to_a
|
96
70
|
end
|
97
71
|
|
98
72
|
def include? value
|
99
|
-
|
73
|
+
self.set.include? value
|
100
74
|
end
|
101
75
|
|
102
76
|
|
@@ -144,7 +118,78 @@ class ImmutableSet
|
|
144
118
|
protected
|
145
119
|
|
146
120
|
def set
|
147
|
-
@set
|
121
|
+
@set ||= @set_change.unrole
|
122
|
+
end
|
123
|
+
|
124
|
+
class SetChange
|
125
|
+
|
126
|
+
def initialize values,set,add,set_change
|
127
|
+
|
128
|
+
raise "set must be supplied" unless set
|
129
|
+
raise "values must be supplied" unless values
|
130
|
+
|
131
|
+
@values = values
|
132
|
+
@set = set
|
133
|
+
@add = add
|
134
|
+
@set_change = set_change
|
135
|
+
@depth = 0
|
136
|
+
|
137
|
+
if set_change
|
138
|
+
# We need to unrole when we have a depth of more than 500 so that we dont couse a SystemStackError
|
139
|
+
if set_change.depth > 4000
|
140
|
+
@set_change = nil
|
141
|
+
@set = set_change.unrole
|
142
|
+
else
|
143
|
+
@depth = set_change.depth + 1
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def set
|
149
|
+
@set
|
150
|
+
end
|
151
|
+
|
152
|
+
def depth
|
153
|
+
@depth
|
154
|
+
end
|
155
|
+
|
156
|
+
def add_change_to_set set
|
157
|
+
|
158
|
+
@set_change.add_change_to_set(set) if @set_change
|
159
|
+
|
160
|
+
if @add
|
161
|
+
@values.each do |value|
|
162
|
+
if value.is_a? ImmutableSet
|
163
|
+
set.merge(value.to_a)
|
164
|
+
elsif value.is_a? Set
|
165
|
+
set.merge(value)
|
166
|
+
elsif value.is_a? Array
|
167
|
+
set.merge(value)
|
168
|
+
else
|
169
|
+
set.add(value)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
else
|
173
|
+
@values.each do |value|
|
174
|
+
if value.is_a? ImmutableSet
|
175
|
+
set.subtract(value.to_a)
|
176
|
+
elsif value.is_a? Set
|
177
|
+
set.subtract(value)
|
178
|
+
elsif value.is_a? Array
|
179
|
+
set.subtract(value)
|
180
|
+
else
|
181
|
+
set.delete(value)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
set
|
187
|
+
end
|
188
|
+
|
189
|
+
def unrole
|
190
|
+
self.add_change_to_set(@set.clone)
|
191
|
+
end
|
192
|
+
|
148
193
|
end
|
149
194
|
|
150
195
|
end
|
data/lib/values/relation.rb
CHANGED
@@ -100,6 +100,14 @@ class Relation
|
|
100
100
|
else
|
101
101
|
throw 'its not of the same heading!'+", #{tuple.heading.inspect} != #{@heading.inspect}"
|
102
102
|
end
|
103
|
+
elsif tuple.is_a?(Array) && tuple.first.is_a?(Tuple)
|
104
|
+
# Check that all tuples are valid
|
105
|
+
tuple.each do |t|
|
106
|
+
if t.heading != @heading
|
107
|
+
throw 'its not of the same heading!'+", #{t.heading.inspect} != #{@heading.inspect}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
Relation.new(@heading).set_body(@body.add tuple)
|
103
111
|
else
|
104
112
|
throw "Only tuples are supported"
|
105
113
|
end
|
data/spec/relation_spec.rb
CHANGED
@@ -31,8 +31,12 @@ describe Relation do
|
|
31
31
|
|
32
32
|
lambda { company = company.add(Tuple.new({:name => 'Nordea AB',:employes => person})) }.should_not raise_error(ArgumentError)
|
33
33
|
lambda { company = company.add(Tuple.new({:name => 'SEB AB',:employes => person_with_length})) }.should raise_error(ArgumentError)
|
34
|
-
|
35
|
-
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns a new relation with the added tuples' do
|
37
|
+
r = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29}))
|
38
|
+
r = r.add([Tuple.new({:name => 'Emma',:age => 30}),Tuple.new({:name => 'Emma',:age => 31})])
|
39
|
+
r.count.should eql 3
|
36
40
|
end
|
37
41
|
|
38
42
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,9 +2,8 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
2
2
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
3
|
|
4
4
|
require 'keso'
|
5
|
-
require '
|
6
|
-
require 'spec/autorun'
|
5
|
+
require 'rspec'
|
7
6
|
|
8
|
-
|
9
|
-
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.mock_with :rspec
|
10
9
|
end
|
data/timeit.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
old_puts = puts
|
4
|
+
@tab_count = 0
|
5
|
+
|
6
|
+
def puts object
|
7
|
+
super "\t"*@tab_count + object.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def timeit name, &block
|
11
|
+
|
12
|
+
@tab_count += 1
|
13
|
+
start_time = Time.now
|
14
|
+
puts ""
|
15
|
+
puts "(#{name}) runing"
|
16
|
+
yield block
|
17
|
+
puts "(#{name}) total time: #{Time.now - start_time}"
|
18
|
+
puts ""
|
19
|
+
|
20
|
+
@tab_count -= 1
|
21
|
+
end
|
22
|
+
|
23
|
+
load 'timeit/relation_bench.rb'
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require './lib/keso.rb'
|
2
|
+
|
3
|
+
|
4
|
+
timeit "Tuple" do
|
5
|
+
|
6
|
+
timeit "Create 1000 tuples" do
|
7
|
+
|
8
|
+
r = []
|
9
|
+
|
10
|
+
1000.times do |i|
|
11
|
+
r << Tuple.new({:name => 'Emma',:age => i})
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
timeit "Create 20000 tuples" do
|
16
|
+
|
17
|
+
r = []
|
18
|
+
|
19
|
+
20000.times do |i|
|
20
|
+
r << Tuple.new({:name => 'Emma',:age => i})
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
timeit "ImmutableSet" do
|
28
|
+
|
29
|
+
timeit "Add 1000 tuples" do
|
30
|
+
|
31
|
+
iset = ImmutableSet.new
|
32
|
+
|
33
|
+
1000.times do |i|
|
34
|
+
iset = iset.add(Tuple.new({:name => 'Emma',:age => i}))
|
35
|
+
end
|
36
|
+
|
37
|
+
iset.count
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
timeit "Add 2000 tuples" do
|
42
|
+
|
43
|
+
iset = ImmutableSet.new
|
44
|
+
|
45
|
+
2000.times do |i|
|
46
|
+
iset = iset.add(Tuple.new({:name => 'Emma',:age => i}))
|
47
|
+
end
|
48
|
+
|
49
|
+
iset.count
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
timeit "Add 20000 tuples" do
|
54
|
+
|
55
|
+
iset = ImmutableSet.new
|
56
|
+
|
57
|
+
20000.times do |i|
|
58
|
+
iset = iset.add(Tuple.new({:name => 'Emma',:age => i}))
|
59
|
+
end
|
60
|
+
|
61
|
+
iset.count
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
timeit "Relation" do
|
69
|
+
|
70
|
+
timeit "Adding 1000 tuples" do
|
71
|
+
|
72
|
+
r = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29}))
|
73
|
+
|
74
|
+
1000.times do |i|
|
75
|
+
r = r.add(Tuple.new({:name => 'Emma',:age => i}))
|
76
|
+
end
|
77
|
+
|
78
|
+
r.count
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
timeit "Adding 2000 tuples" do
|
83
|
+
|
84
|
+
r = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29}))
|
85
|
+
|
86
|
+
2000.times do |i|
|
87
|
+
r = r.add(Tuple.new({:name => 'Emma',:age => i}))
|
88
|
+
end
|
89
|
+
|
90
|
+
r.count
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
timeit "Adding 20000 tuples" do
|
95
|
+
|
96
|
+
r = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29}))
|
97
|
+
|
98
|
+
20000.times do |i|
|
99
|
+
r = r.add(Tuple.new({:name => 'Emma',:age => i}))
|
100
|
+
end
|
101
|
+
|
102
|
+
r.count
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
timeit "Adding 20000 tuples as one array" do
|
107
|
+
|
108
|
+
r = Relation.new(Tuple.new({:name => 'Bjorn',:age => 29}))
|
109
|
+
a = []
|
110
|
+
|
111
|
+
20000.times do |i|
|
112
|
+
a << Tuple.new({:name => 'Emma',:age => i})
|
113
|
+
end
|
114
|
+
|
115
|
+
r.add(a)
|
116
|
+
|
117
|
+
r.count
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 4
|
9
|
+
version: 0.1.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Darwin
|
@@ -14,13 +14,25 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-03-20 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
22
|
-
prerelease: false
|
21
|
+
name: jeweler
|
23
22
|
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
prerelease: false
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rspec
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
24
36
|
none: false
|
25
37
|
requirements:
|
26
38
|
- - ">="
|
@@ -31,7 +43,8 @@ dependencies:
|
|
31
43
|
- 9
|
32
44
|
version: 1.2.9
|
33
45
|
type: :development
|
34
|
-
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *id002
|
35
48
|
description: Cottage cheees with lots of relational theory. Or mabye not so much theory =(
|
36
49
|
email: darwin@markkonsulter.se
|
37
50
|
executables: []
|
@@ -42,8 +55,10 @@ extra_rdoc_files:
|
|
42
55
|
- LICENSE
|
43
56
|
- README.rdoc
|
44
57
|
files:
|
58
|
+
- .bundle/config
|
45
59
|
- .document
|
46
|
-
- .
|
60
|
+
- .rspec
|
61
|
+
- Gemfile
|
47
62
|
- LICENSE
|
48
63
|
- README.rdoc
|
49
64
|
- Rakefile
|
@@ -62,16 +77,17 @@ files:
|
|
62
77
|
- spec/immutable_hash_spec.rb
|
63
78
|
- spec/immutable_set_spec.rb
|
64
79
|
- spec/relation_spec.rb
|
65
|
-
- spec/spec.opts
|
66
80
|
- spec/spec_helper.rb
|
67
81
|
- spec/tuple_spec.rb
|
82
|
+
- timeit.rb
|
83
|
+
- timeit/relation_bench.rb
|
68
84
|
has_rdoc: true
|
69
85
|
homepage: http://github.com/bjornblomqvist/keso
|
70
86
|
licenses: []
|
71
87
|
|
72
88
|
post_install_message:
|
73
|
-
rdoc_options:
|
74
|
-
|
89
|
+
rdoc_options: []
|
90
|
+
|
75
91
|
require_paths:
|
76
92
|
- lib
|
77
93
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -79,6 +95,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
79
95
|
requirements:
|
80
96
|
- - ">="
|
81
97
|
- !ruby/object:Gem::Version
|
98
|
+
hash: -3964452428481869928
|
82
99
|
segments:
|
83
100
|
- 0
|
84
101
|
version: "0"
|