duplo 0.1.1 → 0.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +83 -91
- data/lib/duplo.rb +4 -7
- data/lib/duplo/version.rb +1 -1
- data/spec/duplo_spec.rb +24 -9
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d02593bee25e38b9368df7f965717035db59579
|
4
|
+
data.tar.gz: af814995e2b547a0d85f3ba5cf02b95962b8088b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc9294e2222a29169114d39483d8f624f7507cf0523af3ddbc9961f288ba5331db8107d7101a2cff067ffeca08978f10e8773f2121e0fc94b972ff12e89d76f4
|
7
|
+
data.tar.gz: 84bfb768ff5d817cf694b9f7914baa2dc77589f72d0e1232ee9bb9bde8d36355e8669817832ea87937e6cb6182a64ad8d2e22fb35c99c848263385960679e021
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -4,22 +4,16 @@ Duplo
|
|
4
4
|
[](https://rubygems.org/gems/duplo)
|
5
5
|
[](https://travis-ci.org/topalovic/duplo)
|
6
6
|
|
7
|
-
|
7
|
+
A tiny Ruby DSL for generating collections.
|
8
8
|
|
9
|
-
|
10
|
-
.-===============-.
|
11
|
-
| ( ) ( ) ( ) ( ) |
|
12
|
-
| ( ) ( ) ( ) ( ) |
|
13
|
-
'-----------------' ndt.
|
14
|
-
```
|
9
|
+
<img src="https://cloud.githubusercontent.com/assets/626128/7639329/545932e6-fa7b-11e4-84b0-a64c9e23c9df.png" width="100">
|
15
10
|
|
16
11
|
|
17
12
|
## Usage
|
18
13
|
|
19
|
-
Let's say you like matrices (bear with me)
|
20
|
-
|
21
|
-
|
22
|
-
generating them can be a royal PITA.
|
14
|
+
Let's say you like matrices (bear with me) but not rolling them out by
|
15
|
+
hand. Or say you need to generate some data samples quickly in the
|
16
|
+
console but writing nested loops is not really your idea of fun.
|
23
17
|
|
24
18
|
So how about this:
|
25
19
|
|
@@ -27,126 +21,134 @@ So how about this:
|
|
27
21
|
require "duplo"
|
28
22
|
include Duplo
|
29
23
|
|
30
|
-
|
31
|
-
|
24
|
+
a4a8
|
25
|
+
#=> [[0, 1, 2, 3, 4, 5, 6, 7],
|
26
|
+
# [0, 1, 2, 3, 4, 5, 6, 7],
|
27
|
+
# [0, 1, 2, 3, 4, 5, 6, 7],
|
28
|
+
# [0, 1, 2, 3, 4, 5, 6, 7]]
|
32
29
|
```
|
33
30
|
|
34
|
-
Bam. A
|
31
|
+
Bam. A 4x8 matrix.
|
35
32
|
|
36
|
-
Want it
|
33
|
+
Want it randomized? Just pass it a block to populate the entries:
|
37
34
|
|
38
35
|
```ruby
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# [0.37651300630626683, 0.5035024403835663, 0.8237420938739567, 0.7611012983149591]]
|
36
|
+
a4a8 { rand 10 }
|
37
|
+
#=> [[5, 1, 2, 7, 8, 9, 6, 1],
|
38
|
+
# [7, 6, 6, 0, 7, 1, 0, 8],
|
39
|
+
# [9, 3, 8, 7, 6, 4, 4, 5],
|
40
|
+
# [3, 0, 9, 0, 7, 3, 8, 9]]
|
45
41
|
```
|
46
42
|
|
47
|
-
|
48
|
-
matrix:
|
43
|
+
This works too:
|
49
44
|
|
50
45
|
```ruby
|
51
|
-
|
52
|
-
# => [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
|
46
|
+
Duplo.a4a8
|
53
47
|
```
|
54
48
|
|
55
|
-
|
56
|
-
|
49
|
+
so including the module is optional. The gem works its magic through
|
50
|
+
`method_missing` so it won't stomp on existing names either way.
|
51
|
+
|
52
|
+
|
53
|
+
### Entry path
|
54
|
+
|
55
|
+
Populating the entries is easy peasy. Here, have an identity matrix:
|
57
56
|
|
58
57
|
```ruby
|
59
|
-
|
60
|
-
|
61
|
-
#
|
62
|
-
#
|
58
|
+
I5 = a5a5 { |i, j| i == j ? 1 : 0 }
|
59
|
+
#=> [[1, 0, 0, 0, 0],
|
60
|
+
# [0, 1, 0, 0, 0],
|
61
|
+
# [0, 0, 1, 0, 0],
|
62
|
+
# [0, 0, 0, 1, 0],
|
63
|
+
# [0, 0, 0, 0, 1]
|
63
64
|
```
|
64
65
|
|
65
|
-
|
66
|
-
recursive approach under the hood.
|
67
|
-
|
68
|
-
Now how 'bout them Hashes:
|
66
|
+
If plain old matrices bore you, you can do simple vectors:
|
69
67
|
|
70
68
|
```ruby
|
71
|
-
|
72
|
-
|
73
|
-
# 1=>{0=>{0=>"I'm a 100", 1=>"I'm a 101"}, 1=>{0=>"I'm a 110", 1=>"I'm a 111"}},
|
74
|
-
# 2=>{0=>{0=>"I'm a 200", 1=>"I'm a 201"}, 1=>{0=>"I'm a 210", 1=>"I'm a 211"}}}
|
69
|
+
a10 { |i| i ** 2 }
|
70
|
+
#=> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
|
75
71
|
```
|
76
72
|
|
77
|
-
|
78
|
-
your little heart's desire:
|
73
|
+
or arbitrary tensors:
|
79
74
|
|
80
75
|
```ruby
|
81
|
-
|
82
|
-
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
# {0=>#<Set: {"oq", "vb", "ed"}>, 1=>#<Set: {"gq", "px", "sv"}>}]
|
76
|
+
a4a11a2a3 { |path| path.join(":") }
|
77
|
+
#=> [[[["0:0:0:0", "0:0:0:1", "0:0:0:2"],
|
78
|
+
# ["0:0:1:0", "0:0:1:1", "0:0:1:2"]],
|
79
|
+
# . . .
|
80
|
+
# ["3:10:1:0", "3:10:1:1", "3:10:1:2"]]]]
|
87
81
|
```
|
88
82
|
|
89
|
-
|
90
|
-
|
83
|
+
The last example also shows how to use the full entry path without
|
84
|
+
destructuring.
|
85
|
+
|
86
|
+
|
87
|
+
### Other toys
|
88
|
+
|
89
|
+
In addition to `a`rrays, you can build `h`ashes and `s`ets, and mix
|
90
|
+
and match collection types to your heart's desire:
|
91
91
|
|
92
92
|
```ruby
|
93
|
-
|
94
|
-
|
93
|
+
sa2h3 { rand 100 }
|
94
|
+
#=> #<Set: {[{0=>11, 1=>47, 2=>48}, {0=>3, 1=>71, 2=>57}],
|
95
|
+
# [{0=>97, 1=>9, 2=>43}, {0=>90, 1=>30, 2=>62}],
|
96
|
+
# [{0=>87, 1=>56, 2=>23}, {0=>24, 1=>16, 2=>63}],
|
97
|
+
# [{0=>6, 1=>12, 2=>57}, {0=>44, 1=>3, 2=>74}],
|
98
|
+
# [{0=>52, 1=>92, 2=>12}, {0=>93, 1=>32, 2=>1}]}>
|
95
99
|
```
|
96
100
|
|
97
|
-
|
98
|
-
example. It defaults to 5, so `as2h` means the same thing as
|
99
|
-
`a5s2h5`. You can easily change it like this:
|
101
|
+
Let's spell that out:
|
100
102
|
|
101
103
|
```ruby
|
102
|
-
Duplo.
|
104
|
+
Duplo.spell "sa2h3"
|
105
|
+
#=> "5-element Set containing 2-element Arrays containing 3-element Hashes"
|
103
106
|
```
|
104
107
|
|
105
|
-
|
106
|
-
|
108
|
+
Note that I've omitted size for the root collection there. It defaults
|
109
|
+
to 5, so `aaa` yields the same result as `a5a5a5`. Set your preferred
|
110
|
+
default like this:
|
107
111
|
|
112
|
+
```ruby
|
113
|
+
Duplo.default_size = 10
|
114
|
+
```
|
108
115
|
|
109
|
-
## Installation
|
110
116
|
|
111
|
-
|
117
|
+
### Dynamic dimensions
|
112
118
|
|
113
|
-
|
114
|
-
"development" or "test" group:
|
119
|
+
If you want to supply dimensions dynamically, this should do the trick:
|
115
120
|
|
116
121
|
```ruby
|
117
|
-
|
122
|
+
m, n = 3, 4
|
123
|
+
toy = "a#{m}a#{n}"
|
124
|
+
|
125
|
+
Duplo.build(toy) { rand }
|
118
126
|
```
|
119
127
|
|
120
|
-
or install it yourself as:
|
121
128
|
|
122
|
-
|
123
|
-
$ gem install duplo
|
124
|
-
```
|
129
|
+
## Installation
|
125
130
|
|
126
|
-
|
127
|
-
directly:
|
131
|
+
Add this line to your application's Gemfile:
|
128
132
|
|
129
133
|
```ruby
|
130
|
-
|
134
|
+
gem "duplo"
|
131
135
|
```
|
132
136
|
|
133
|
-
|
134
|
-
works its magic by utilizing `method_missing`, so there should be no
|
135
|
-
name clashes.
|
137
|
+
or install it yourself as:
|
136
138
|
|
137
|
-
|
139
|
+
```sh
|
140
|
+
$ gem install duplo
|
141
|
+
```
|
138
142
|
|
143
|
+
My personal preference is to drop this into `.irbrc` (or `.pryrc`):
|
139
144
|
|
140
145
|
```ruby
|
141
|
-
|
142
|
-
|
143
|
-
include Duplo
|
144
|
-
rescue LoadError
|
145
|
-
end
|
146
|
+
require "duplo"
|
147
|
+
include Duplo
|
146
148
|
```
|
147
149
|
|
148
|
-
and have those handy shortcuts available in every session
|
149
|
-
|
150
|
+
and have all those handy shortcuts available in every session.
|
151
|
+
|
150
152
|
|
151
153
|
|
152
154
|
## Testing
|
@@ -154,20 +156,10 @@ in particular.
|
|
154
156
|
To test the gem, clone the repo and run:
|
155
157
|
|
156
158
|
```
|
157
|
-
$ bundle
|
158
|
-
$ bundle exec rake
|
159
|
+
$ bundle && bundle exec rake
|
159
160
|
```
|
160
161
|
|
161
162
|
|
162
|
-
## Contributing
|
163
|
-
|
164
|
-
1. [Fork it](https://github.com/topalovic/duplo/fork)
|
165
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
166
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
167
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
168
|
-
5. Create a new pull request
|
169
|
-
|
170
|
-
|
171
163
|
## License
|
172
164
|
|
173
165
|
This gem is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/lib/duplo.rb
CHANGED
@@ -33,14 +33,16 @@ module Duplo
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def build(part, path = [], &block)
|
36
|
+
raise %(Don't know how to build "#{part}", sorry) unless can_build? part
|
37
|
+
|
36
38
|
part = part.dup
|
37
39
|
brick = part.slice! BRICK
|
38
40
|
type, size = crack brick
|
39
41
|
toy = type.new
|
40
42
|
|
41
43
|
if part.empty?
|
42
|
-
|
43
|
-
size.times { |i| add toy,
|
44
|
+
block ||= proc { |path| path.is_a?(Array) ? path.last : path }
|
45
|
+
size.times { |i| add toy, block.call(path.empty? ? i : path + [i]) }
|
44
46
|
else
|
45
47
|
size.times { |i| add toy, build(part, path + [i], &block) }
|
46
48
|
end
|
@@ -68,11 +70,6 @@ module Duplo
|
|
68
70
|
|
69
71
|
module_function
|
70
72
|
|
71
|
-
def abc(n = nil)
|
72
|
-
range = "a".."z"
|
73
|
-
n ? range.take(n) : range.to_a
|
74
|
-
end
|
75
|
-
|
76
73
|
def respond_to_missing?(method_name, *)
|
77
74
|
toy = method_name.to_s
|
78
75
|
Duplo.can_build?(toy) || super
|
data/lib/duplo/version.rb
CHANGED
data/spec/duplo_spec.rb
CHANGED
@@ -2,21 +2,14 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Duplo do
|
4
4
|
|
5
|
-
let(:default_size)
|
5
|
+
let(:default_size) { Duplo.default_size }
|
6
6
|
let(:valid_bricks) { %w[a aa s ss h hh a0 a1h a2s33h44] }
|
7
7
|
let(:invalid_bricks) { %w[A n 0 11 1s a2s33t44] }
|
8
8
|
|
9
|
-
|
9
|
+
it "has a version number" do
|
10
10
|
expect(Duplo::VERSION).not_to be nil
|
11
11
|
end
|
12
12
|
|
13
|
-
describe ".abc" do
|
14
|
-
it "provides alphabet" do
|
15
|
-
expect(Duplo.abc).to eq ("a".."z").to_a
|
16
|
-
expect(Duplo.abc 4).to eq ("a".."d").to_a
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
13
|
describe ".respond_to?" do
|
21
14
|
it "returns true for valid bricks" do
|
22
15
|
valid_bricks.each do |brick|
|
@@ -62,6 +55,28 @@ describe Duplo do
|
|
62
55
|
expect(Duplo.build brick).to eq toy
|
63
56
|
end
|
64
57
|
end
|
58
|
+
|
59
|
+
it "raises error when given invalid brick" do
|
60
|
+
invalid_bricks.each do |brick|
|
61
|
+
expect { Duplo.build brick }.to raise_error RuntimeError
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "when given a block" do
|
66
|
+
let(:block) { proc { |entry| entry.class } }
|
67
|
+
|
68
|
+
describe "when given one dimension" do
|
69
|
+
it "yields entry path as integer and populates entries" do
|
70
|
+
expect(Duplo.build "a1", &block).to eq [Fixnum]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "when given more than one dimension" do
|
75
|
+
it "yields entry path as array and populates entries" do
|
76
|
+
expect(Duplo.build "a1a1", &block).to eq [[Array]]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
65
80
|
end
|
66
81
|
|
67
82
|
describe ".smash" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: duplo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nikola Topalović
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -71,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
71
|
version: '0'
|
72
72
|
requirements: []
|
73
73
|
rubyforge_project:
|
74
|
-
rubygems_version: 2.4.
|
74
|
+
rubygems_version: 2.4.6
|
75
75
|
signing_key:
|
76
76
|
specification_version: 4
|
77
77
|
summary: Generate nested collections with minimum effort.
|