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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ced13192f8a77859809d3f5152405b8b8277d422
4
- data.tar.gz: 82096e9fd70ffb4a938ace1f83cf69bbd5a1cd38
3
+ metadata.gz: 0d02593bee25e38b9368df7f965717035db59579
4
+ data.tar.gz: af814995e2b547a0d85f3ba5cf02b95962b8088b
5
5
  SHA512:
6
- metadata.gz: 81567d7e7c0185dde4fcb4982a56fd09c2fd65093ef0ce0487ec908b8fe2dec9f78210ce81a125e19b31e1139de89b934ff63b34fb147c19c1893d1edadda908
7
- data.tar.gz: 32845ca94f81a928a665353c463320e7ac991c4ebe90e00f84f7e30fbb0f882be8f3245c7cf4e293bf9a6689a82f73dfe8035bafc552b61475ba25be78ed1a21
6
+ metadata.gz: cc9294e2222a29169114d39483d8f624f7507cf0523af3ddbc9961f288ba5331db8107d7101a2cff067ffeca08978f10e8773f2121e0fc94b972ff12e89d76f4
7
+ data.tar.gz: 84bfb768ff5d817cf694b9f7914baa2dc77589f72d0e1232ee9bb9bde8d36355e8669817832ea87937e6cb6182a64ad8d2e22fb35c99c848263385960679e021
@@ -1,5 +1,10 @@
1
1
  # Duplo changelog
2
2
 
3
+ ### 0.1.2 (2015-08-30)
4
+
5
+ * Yield integers for vector entries instead of arrays
6
+ * Drop `#abc`
7
+
3
8
  ### 0.1.1 (2015-05-09)
4
9
 
5
10
  * Provide `#respond_to_missing?`
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
- Generate nested collections with minimum effort.
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), but not rolling them out
20
- by hand or writing nested loops to populate them. Or you might need a
21
- few nested hashes to test something real quick in the console, but
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
- a3a4
31
- # => [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
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 3x4 matrix.
31
+ Bam. A 4x8 matrix.
35
32
 
36
- Want it random? Sure. Pass it a block to populate the entries:
33
+ Want it randomized? Just pass it a block to populate the entries:
37
34
 
38
35
  ```ruby
39
- a3a4 { rand -5..5 }
40
- # => [[1, 9, 8, 3], [3, 0, -1, -2], [2, 0, 5, -7]]
41
- a3a4 { rand }
42
- # => [[0.6222777300676433, 0.5613390139342668, 0.37293736375203324, 0.7319666374054961],
43
- # [0.3798588109025701, 0.33483069318178915, 0.8779112502970073, 0.22476545143154103],
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
- Accessing the current entry path is easy peasy. Have an identity
48
- matrix:
43
+ This works too:
49
44
 
50
45
  ```ruby
51
- I4 = a4a4 { |i, j| i == j ? 1 : 0 }
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
- Have I mentioned that you can go up to an arbitrary number of
56
- dimensions?
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
- a3a3a2 { |i,j,k| [i,j,k].join(":") }
60
- # => [[["0:0:0", "0:0:1"], ["0:1:0", "0:1:1"], ["0:2:0", "0:2:1"]],
61
- # [["1:0:0", "1:0:1"], ["1:1:0", "1:1:1"], ["1:2:0", "1:2:1"]],
62
- # [["2:0:0", "2:0:1"], ["2:1:0", "2:1:1"], ["2:2:0", "2:2:1"]]]
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
- Heads up, it might get a bit sluggish with higher dims due to the
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
- h3h2h2 { |path| "I'm a #{path.join}" }
72
- # => {0=>{0=>{0=>"I'm a 000", 1=>"I'm a 001"}, 1=>{0=>"I'm a 010", 1=>"I'm a 011"}},
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
- You can also use `s` for Sets, and mix and match collection types to
78
- your little heart's desire:
73
+ or arbitrary tensors:
79
74
 
80
75
  ```ruby
81
- ah2s3 { abc.sample(2).join }
82
- # => [{0=>#<Set: {"kx", "by", "fi"}>, 1=>#<Set: {"uz", "ow", "tx"}>},
83
- # {0=>#<Set: {"tp", "ch", "ba"}>, 1=>#<Set: {"nu", "mn", "ve"}>},
84
- # {0=>#<Set: {"nc", "dh", "dc"}>, 1=>#<Set: {"le", "ks", "th"}>},
85
- # {0=>#<Set: {"ca", "xj", "lm"}>, 1=>#<Set: {"hg", "xg", "rz"}>},
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
- You get the picture. If you're *really* bored, you can spell those out
90
- loud:
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
- Duplo.spell "ah2s0"
94
- # => "5-element Array containing 2-element Hashes containing empty Sets"
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
- Note that I've omitted a dim for the root array in that last
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.default_size = 3
104
+ Duplo.spell "sa2h3"
105
+ #=> "5-element Set containing 2-element Arrays containing 3-element Hashes"
103
106
  ```
104
107
 
105
- Also, I sneaked in a cute little `abc` method that returns the
106
- alphabet as an array (as seen in the last example).
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
- You know the drill.
117
+ ### Dynamic dimensions
112
118
 
113
- Add this line to your application's Gemfile, presumably in the
114
- "development" or "test" group:
119
+ If you want to supply dimensions dynamically, this should do the trick:
115
120
 
116
121
  ```ruby
117
- gem "duplo"
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
- ```console
123
- $ gem install duplo
124
- ```
129
+ ## Installation
125
130
 
126
- It's not really necessary to include the module, you can use it
127
- directly:
131
+ Add this line to your application's Gemfile:
128
132
 
129
133
  ```ruby
130
- Duplo.a2a2
134
+ gem "duplo"
131
135
  ```
132
136
 
133
- If you do include it, don't worry about monkey patching - the gem
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
- My personal preference is to drop this in `.pryrc` (or `.irbrc`):
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
- begin
142
- require "duplo"
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, `a` and `h`
149
- in particular.
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).
@@ -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
- _block = block_given? ? block : proc { |path| path.last }
43
- size.times { |i| add toy, _block.call(path + [i]) }
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
@@ -1,3 +1,3 @@
1
1
  module Duplo
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -2,21 +2,14 @@ require "spec_helper"
2
2
 
3
3
  describe Duplo do
4
4
 
5
- let(:default_size) { Duplo.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
- it "has a version number" do
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.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-05-09 00:00:00.000000000 Z
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.5
74
+ rubygems_version: 2.4.6
75
75
  signing_key:
76
76
  specification_version: 4
77
77
  summary: Generate nested collections with minimum effort.