colby 0.0.1
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/.gitignore +2 -0
- data/Gemfile +2 -0
- data/README.md +28 -0
- data/colby.gemspec +23 -0
- data/lib/colby.rb +3 -0
- data/lib/colby/core.rb +114 -0
- data/lib/colby/version.rb +3 -0
- data/spec/core_spec.rb +148 -0
- metadata +103 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Colby
|
2
|
+
|
3
|
+
Experimenting with bringing Clojure's goodness in Ruby.
|
4
|
+
|
5
|
+
- This project depends on [Hamster](https://github.com/harukizaemon/hamster)
|
6
|
+
- The basic idea for now is to have something broadly equivalent to [Mori](http://swannodette.github.com/mori/), but in Ruby
|
7
|
+
|
8
|
+
## Testing
|
9
|
+
|
10
|
+
- `rspec .`
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
- make sure you have 1.9.3-p194
|
15
|
+
- `bundle install`
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require './colby.rb'
|
19
|
+
|
20
|
+
include Colby::Core
|
21
|
+
|
22
|
+
# Now you can build hash_map, vec, list, or set
|
23
|
+
|
24
|
+
# Also, you have clojure-like functions such as assoc, get, conj, has_key
|
25
|
+
|
26
|
+
# check the spec to see examples
|
27
|
+
|
28
|
+
```
|
data/colby.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$: << "#{File.dirname(__FILE__)}/lib"
|
2
|
+
require 'colby'
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Gursimran Singh"]
|
6
|
+
gem.email = ["g@kilotau.com"]
|
7
|
+
gem.description = %q{Small wrapper and functions for persistent, immutable data structures.}
|
8
|
+
gem.summary = %q{Colby makes it easier to work with persistent, immutable data structures.
|
9
|
+
It wraps Hamster's excellent data structures and provides functions to work
|
10
|
+
with them that are similar to Clojure, but not exactly.}
|
11
|
+
gem.homepage = "http://github.com/gnarmis/colby"
|
12
|
+
|
13
|
+
gem.add_development_dependency('rake')
|
14
|
+
gem.add_development_dependency('rspec')
|
15
|
+
|
16
|
+
gem.add_dependency('hamster')
|
17
|
+
|
18
|
+
gem.files = `git ls-files`.split($/)
|
19
|
+
gem.executables = gem.files.grep(%r{^bin/}).map {|f| File.basename(f)}
|
20
|
+
gem.name = "colby"
|
21
|
+
gem.require_paths = ["lib"]
|
22
|
+
gem.version = Colby::VERSION
|
23
|
+
end
|
data/lib/colby.rb
ADDED
data/lib/colby/core.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'hamster'
|
2
|
+
|
3
|
+
class IndexOutOfBounds < Exception; end
|
4
|
+
|
5
|
+
module Colby
|
6
|
+
module Core
|
7
|
+
|
8
|
+
def hash_map(*pairs)
|
9
|
+
return Hamster.hash(Hash[*pairs]) if pairs.is_a? Array
|
10
|
+
return Hamster.hash(*pairs) if pairs.is_a? Hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def vec(*data)
|
14
|
+
Hamster.vector(*data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def list(*data)
|
18
|
+
Hamster.list(*data)
|
19
|
+
end
|
20
|
+
|
21
|
+
def set(*data)
|
22
|
+
Hamster.set(*data)
|
23
|
+
end
|
24
|
+
|
25
|
+
def conj(coll, item)
|
26
|
+
return coll.cons(item) if coll.is_a? Hamster::List
|
27
|
+
return coll.add(item) if coll.is_a? Hamster::Vector
|
28
|
+
return coll.merge(item) if coll.is_a? Hamster::Hash
|
29
|
+
return Hamster.set(*coll, item) if coll.is_a? Hamster::Set
|
30
|
+
end
|
31
|
+
|
32
|
+
def assoc(coll, *pairs)
|
33
|
+
@retval = coll
|
34
|
+
pairs.each_slice(2) do |k,v|
|
35
|
+
@retval = assoc_2(@retval, k , v)
|
36
|
+
end
|
37
|
+
@retval
|
38
|
+
end
|
39
|
+
|
40
|
+
def assoc_2(coll, key, val)
|
41
|
+
if coll.is_a? Hamster::Hash
|
42
|
+
return coll.send(:put, key) {val}
|
43
|
+
end
|
44
|
+
if coll.is_a? Hamster::Vector
|
45
|
+
if has_key(coll, key)
|
46
|
+
return coll.send(:set, key, val)
|
47
|
+
else
|
48
|
+
raise IndexOutOfBounds
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def get(coll, key)
|
54
|
+
coll.get(key) unless coll.is_a? Hamster::List
|
55
|
+
end
|
56
|
+
|
57
|
+
def nth(coll, key)
|
58
|
+
return get(coll, key) if coll.is_a? Hamster::Vector
|
59
|
+
return coll.to_a[key] if coll.is_a? Hamster::List
|
60
|
+
end
|
61
|
+
|
62
|
+
def find(coll, key)
|
63
|
+
return Core.vec(key, Core.get(coll, key)) if coll.is_a? Hamster::Vector
|
64
|
+
return Core.vec(key, Core.get(coll,key)) if coll.is_a? Hamster::Hash
|
65
|
+
end
|
66
|
+
|
67
|
+
def has_key(coll, key)
|
68
|
+
return coll.has_key?(key) if coll.is_a? Hamster::Hash
|
69
|
+
return coll[key] != nil if (coll.is_a? Hamster::Vector) || (coll.is_a? Hamster::Set)
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def count(coll)
|
74
|
+
return coll.length
|
75
|
+
end
|
76
|
+
|
77
|
+
def peek(coll)
|
78
|
+
return coll.head if coll.is_a? Hamster::List
|
79
|
+
return coll.last if coll.is_a? Hamster::Vector
|
80
|
+
end
|
81
|
+
|
82
|
+
def pop(coll)
|
83
|
+
return coll.tail if coll.is_a? Hamster::List
|
84
|
+
if coll.is_a? Hamster::Vector
|
85
|
+
return vec(*coll.to_a[0..-2])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def zip_map(coll1, coll2)
|
90
|
+
return hash_map(Hash[coll1.to_a.zip(coll2.to_a)])
|
91
|
+
end
|
92
|
+
|
93
|
+
def seq(data)
|
94
|
+
if data.is_a? Hamster::List
|
95
|
+
return data
|
96
|
+
elsif data.is_a? Array or data.is_a? Hamster::Vector
|
97
|
+
return list(*data)
|
98
|
+
elsif data.is_a? Hash
|
99
|
+
return list(*data.keys.to_a.zip(data.values.to_a))
|
100
|
+
elsif data.is_a? Hamster::Hash
|
101
|
+
l = list
|
102
|
+
data.foreach {|k,v| l = conj(l,(list k, v))}
|
103
|
+
return l
|
104
|
+
elsif data.is_a? Hamster::Set
|
105
|
+
return (list(*data)).sort
|
106
|
+
elsif data.is_a? String
|
107
|
+
return list(*data.split(""))
|
108
|
+
else
|
109
|
+
raise Exception
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
data/spec/core_spec.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
$: << "#{File.dirname(__FILE__)}/../lib"
|
2
|
+
|
3
|
+
require 'colby'
|
4
|
+
|
5
|
+
include Colby::Core
|
6
|
+
|
7
|
+
describe "Colby" do
|
8
|
+
|
9
|
+
describe "Core" do
|
10
|
+
|
11
|
+
it "should construct hash-maps given a Ruby Hash" do
|
12
|
+
hash_map(:a => 1).should == Hamster.hash(:a => 1)
|
13
|
+
end
|
14
|
+
it "should construct vectors given values" do
|
15
|
+
vec(1,2,3).should == Hamster.vector(1,2,3)
|
16
|
+
end
|
17
|
+
it "should construct lists given values" do
|
18
|
+
list(1,2,3).should == Hamster.list(1,2,3)
|
19
|
+
end
|
20
|
+
it "should construct sets given values" do
|
21
|
+
set(1,2,3,3).should == Hamster.set(1,2,3,3)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should conj items to head of list" do
|
25
|
+
conj(list(1,2,3), 0).should == list(0,1,2,3)
|
26
|
+
end
|
27
|
+
it "should conj items to end of vector" do
|
28
|
+
conj(vec(1,2,3), 0).should == vec(1,2,3,0)
|
29
|
+
end
|
30
|
+
it "should conj hash_maps by merging them" do
|
31
|
+
conj(hash_map(:a=>1),
|
32
|
+
hash_map(:b=>2,:c=>3)).should == hash_map(:a=>1,:b=>2,:c=>3)
|
33
|
+
end
|
34
|
+
it "should assoc new key-value pairs when conj'ing hash_maps" do
|
35
|
+
conj(hash_map(:a=>1),
|
36
|
+
hash_map(:a=>2,:c=>3)).should == hash_map(:a=>2,:c=>3)
|
37
|
+
end
|
38
|
+
it "should conj sets by making a bigger set" do
|
39
|
+
conj(set(1,2,3,3), 4).should == set(1,2,3,4)
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
it "should assoc any number of pairs into a hash_map collection" do
|
44
|
+
assoc(hash_map(:a=>1),
|
45
|
+
:a, 2,
|
46
|
+
:b, 3,
|
47
|
+
:c, 4).should == hash_map(:a=>2,
|
48
|
+
:b=>3,
|
49
|
+
:c=>4)
|
50
|
+
end
|
51
|
+
it "should assoc index-bounded pairs into a vector collection" do
|
52
|
+
assoc(vec(1,2,3),0,4,1,5,2,6).should == vec(4,5,6)
|
53
|
+
end
|
54
|
+
it "should raise an exception if unbounded pairs used to assoc into a vec" do
|
55
|
+
expect {assoc(vec(1,2),9,9)}.to raise_error
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
it "should return value when using get with a hash_map" do
|
60
|
+
get( hash_map(:a=>1), :a).should == 1
|
61
|
+
end
|
62
|
+
it "should return value when using get with a vector" do
|
63
|
+
get( vec(1,2), 0).should == 1
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
it "should return value when using nth with a vec" do
|
68
|
+
nth(vec(1,2,3), 0).should == 1
|
69
|
+
end
|
70
|
+
it "should return value when using nth with a list" do
|
71
|
+
nth(list(1,2,3), 0).should == 1
|
72
|
+
end
|
73
|
+
it "should not return value when using nth with a set" do
|
74
|
+
nth(set(1,2,3), 0).should_not == 1
|
75
|
+
end
|
76
|
+
it "should not return value when using nth with a hash_map" do
|
77
|
+
nth(hash_map(1,2,3,4), 1).should_not == 2
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
it "should return key/val pair as a vector for a vector" do
|
83
|
+
find(vec(1,2),0).should == vec(0,1)
|
84
|
+
end
|
85
|
+
it "should return key/val pair as a vector for a hash_map" do
|
86
|
+
find(hash_map(1,2,3,4), 3).should == vec(3,4)
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
it "should return bool if vec has or doesn't have key" do
|
91
|
+
has_key(vec(1,2), 0).should == true
|
92
|
+
has_key(vec(1,2), 3).should == false
|
93
|
+
end
|
94
|
+
it "should return bool if hash_map has or doesn't have key" do
|
95
|
+
has_key(hash_map(:a=>1), :a).should == true
|
96
|
+
has_key(hash_map(:a=>1), 3).should == false
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
it "should return count for lists" do
|
101
|
+
count(list(1,2,3)).should == 3
|
102
|
+
end
|
103
|
+
it "should return count for vectors" do
|
104
|
+
count(vec(1,2,3)).should == 3
|
105
|
+
end
|
106
|
+
it "should return count for sets" do
|
107
|
+
count(set(1,2,3)).should == 3
|
108
|
+
end
|
109
|
+
it "should return count for hash_maps" do
|
110
|
+
count(hash_map(1=>2,3=>4)).should == 2
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
it "should return head of list when using peek" do
|
115
|
+
peek(list(1,2,3)).should == 1
|
116
|
+
end
|
117
|
+
it "should return last element of vec when using peek" do
|
118
|
+
peek(vec(1,2,3)).should == 3
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
it "should return list with head removed when using pop" do
|
123
|
+
pop(list(1,2,3)).should == list(2,3)
|
124
|
+
end
|
125
|
+
it "should return vec with last item removed when using pop" do
|
126
|
+
pop(vec(1,2,3)).should == vec(1,2)
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
it "should zip two seqs into a hash_map" do
|
131
|
+
zip_map(vec(1,2,3), list(4,5,6)).should == hash_map(1,4,2,5,3,6)
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
it "should convert Arrays, lists, and vecs into a seq (list)" do
|
136
|
+
seq([1,2,4,3]).should == list(1,2,4,3)
|
137
|
+
seq(list(1,2,4,3)).should == list(1,2,4,3)
|
138
|
+
seq(vec(1,2,4,3)).should == list(1,2,4,3)
|
139
|
+
end
|
140
|
+
it "should convert a Hash into a seq" do
|
141
|
+
seq(hash_map(:a,2)).should == list(list(:a,2))
|
142
|
+
end
|
143
|
+
it "should convert a String into a seq" do
|
144
|
+
seq("abc").should == list("a","b","c")
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: colby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Gursimran Singh
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: hamster
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Small wrapper and functions for persistent, immutable data structures.
|
63
|
+
email:
|
64
|
+
- g@kilotau.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- Gemfile
|
71
|
+
- README.md
|
72
|
+
- colby.gemspec
|
73
|
+
- lib/colby.rb
|
74
|
+
- lib/colby/core.rb
|
75
|
+
- lib/colby/version.rb
|
76
|
+
- spec/core_spec.rb
|
77
|
+
homepage: http://github.com/gnarmis/colby
|
78
|
+
licenses: []
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 1.8.24
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: Colby makes it easier to work with persistent, immutable data structures.
|
101
|
+
It wraps Hamster's excellent data structures and provides functions to work with
|
102
|
+
them that are similar to Clojure, but not exactly.
|
103
|
+
test_files: []
|