duplo 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/duplo.svg)](https://rubygems.org/gems/duplo)
|
5
5
|
[![Build Status](https://travis-ci.org/topalovic/duplo.svg?branch=master)](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.
|