ioughta 0.2.1 → 0.3.0
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/README.md +51 -27
- data/ioughta.gemspec +1 -1
- data/lib/ioughta.rb +12 -30
- data/lib/ioughta/version.rb +1 -1
- 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: 7918cd422602dfb4b8d10a0a22a41ecd7385d092
|
4
|
+
data.tar.gz: 529732cd9cfc9f3e8dc9f11422aaaa43dea9a35e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c64d851fb46da155fb80c475ba9ae391cb3deee69106f196e35a5c9c99a45b275ddc4d6f8197cdd98164b2614a44cc58dac40d9f2d33cd2eb3a0204711257a7
|
7
|
+
data.tar.gz: c7ac30fba3192205a238ac82b4fb3833a523b0f7c063611ab5bee3ad3e1baaf85d4e43d8434ab09a26ea401542edaf23710753a52ea2a037189c2eb55e52958b
|
data/README.md
CHANGED
@@ -3,28 +3,36 @@
|
|
3
3
|
[](https://travis-ci.org/mwpastore/ioughta)
|
4
4
|
[](https://badge.fury.io/rb/ioughta)
|
5
5
|
|
6
|
-
Helpers for defining
|
6
|
+
Helpers for defining sequences of constants in Ruby using a Go-like syntax.
|
7
7
|
|
8
8
|
Go has quite a nice facility for defining constants derived from a sequential
|
9
9
|
value using a [simple and elegant syntax][1], so I thought I'd steal it for
|
10
10
|
Ruby. Rubyists tend to group constants together in hashes rather than littering
|
11
11
|
their programs with countless constants, so there's a mechanism for that, too.
|
12
12
|
|
13
|
-
|
13
|
+
Although there isn't as strong of a need for sequences of constants in Ruby as
|
14
|
+
there is in other languages such as Go, they are still sometimes required when
|
15
|
+
working with external systems such as databases and web APIs for which Ruby
|
16
|
+
symbols don't map cleanly. For example, a database column might store users'
|
17
|
+
privilege levels as 0, 1, or 2, and it would be useful to define constants that
|
18
|
+
map to those values. Ruby doesn't have a native expression for this construct
|
19
|
+
(other than simply defining them one at a time).
|
20
|
+
|
21
|
+
Here's a simple example, written in Go:
|
14
22
|
|
15
23
|
```go
|
16
24
|
type Allergen int
|
17
25
|
|
18
26
|
const (
|
19
|
-
IgEggs Allergen = 1 << iota
|
20
|
-
IgChocolate
|
21
|
-
IgNuts
|
22
|
-
IgStrawberries
|
23
|
-
IgShellfish
|
27
|
+
IgEggs Allergen = 1 << iota // 1 << 0 which is 00000001
|
28
|
+
IgChocolate // 1 << 1 which is 00000010
|
29
|
+
IgNuts // 1 << 2 which is 00000100
|
30
|
+
IgStrawberries // 1 << 3 which is 00001000
|
31
|
+
IgShellfish // 1 << 4 which is 00010000
|
24
32
|
)
|
25
33
|
```
|
26
34
|
|
27
|
-
|
35
|
+
And here it is in Ruby, using ioughta:
|
28
36
|
|
29
37
|
```ruby
|
30
38
|
Object.ioughta_const(
|
@@ -41,15 +49,15 @@ IG_STRAWBERRIES # => 8
|
|
41
49
|
Or, perhaps a bit more Rubyishly:
|
42
50
|
|
43
51
|
```ruby
|
44
|
-
IG = Object.
|
52
|
+
IG = Object.iota_hash(%i[
|
45
53
|
eggs
|
46
54
|
chocolate
|
47
55
|
nuts
|
48
56
|
strawberries
|
49
57
|
shellfish
|
50
|
-
]).freeze
|
58
|
+
]) { |i| 1 << i }.freeze
|
51
59
|
|
52
|
-
IG[:
|
60
|
+
IG[:shellfish] # => 16
|
53
61
|
```
|
54
62
|
|
55
63
|
## Installation
|
@@ -76,9 +84,11 @@ $ gem install ioughta
|
|
76
84
|
|
77
85
|
Ioughta works just like `const` and `iota` do in Go, with only a few minor
|
78
86
|
differences. You must `include` the module in your program, class, or module in
|
79
|
-
order to start using it. The iterator starts at zero (
|
80
|
-
each constant
|
81
|
-
|
87
|
+
order to start using it. The iterator starts at zero (0) and increments for
|
88
|
+
each constant (or hash key) being defined. A function (any Ruby callable) takes
|
89
|
+
the current iteration as input and returns the value to be assigned. The
|
90
|
+
default function simply returns the iterator, so you can easily create
|
91
|
+
sequences of constants with consecutive integer values:
|
82
92
|
|
83
93
|
```ruby
|
84
94
|
require 'ioughta'
|
@@ -86,6 +96,8 @@ include Ioughta
|
|
86
96
|
|
87
97
|
Object.ioughta_const(:FOO, :BAR, :QUX)
|
88
98
|
|
99
|
+
FOO # => 0
|
100
|
+
BAR # => 1
|
89
101
|
QUX # => 2
|
90
102
|
```
|
91
103
|
|
@@ -94,13 +106,14 @@ To skip value(s) in the sequence, use the `:_` symbol:
|
|
94
106
|
```ruby
|
95
107
|
Object.ioughta_const(:_, :FOO, :BAR, :_, :QUX)
|
96
108
|
|
109
|
+
FOO # => 1
|
110
|
+
BAR # => 2
|
97
111
|
QUX # => 4
|
98
112
|
```
|
99
113
|
|
100
|
-
As soon as Ioughta sees a lambda, it will start using it
|
101
|
-
values from the iterator.
|
102
|
-
|
103
|
-
the lambda as many times as you like:
|
114
|
+
As soon as Ioughta sees a lambda (or any Ruby callable), it will start using it
|
115
|
+
to generate future values from the iterator. You can redefine the lambda as
|
116
|
+
many times as you like:
|
104
117
|
|
105
118
|
```ruby
|
106
119
|
Object.ioughta_const(
|
@@ -110,35 +123,42 @@ Object.ioughta_const(
|
|
110
123
|
:D, ->(j) { j ** 3 }, # will cube (3 => 27)
|
111
124
|
:E, # will also cube (4 => 64)
|
112
125
|
:F, # cube all the things (5 => 125)
|
113
|
-
:G,
|
126
|
+
:G, ->{ 0.5 } # will use a simple value (6 => 0.5)
|
127
|
+
:H, proc(&:itself) # restore the default behavior (7 => 7)
|
114
128
|
)
|
115
129
|
```
|
116
130
|
|
117
131
|
You can also pass the lambda as the first argument:
|
118
132
|
|
119
133
|
```ruby
|
120
|
-
Object.
|
134
|
+
Object.Ioughta_const ->(I) { 1 << (10 * I) }, %I[_ KIB MIB GIB TIB PIB EIB ZIB YIB]
|
121
135
|
```
|
122
136
|
|
123
137
|
Or even pass a block, instead of a lambda:
|
124
138
|
|
125
139
|
```ruby
|
126
|
-
BYTES = Object.ioughta_hash(%i[_ KB MB GB TB PB EB ZB YB]) { |i|
|
140
|
+
BYTES = Object.ioughta_hash(%i[_ KB MB GB TB PB EB ZB YB]) { |i| 10 ** (i * 3) }.freeze
|
127
141
|
```
|
128
142
|
|
143
|
+
If the first argument is a lambda *and* a block is given, the block will be
|
144
|
+
silently ignored.
|
145
|
+
|
146
|
+
## Notes
|
147
|
+
|
129
148
|
The only major feature missing from the Go implementation is the ability to
|
130
149
|
perform parallel assignment in the constant list. We're defining a list of
|
131
150
|
terms, not a list of expressions, so it's not possible to do in Ruby without
|
132
|
-
resourcing to nasty `eval` tricks. Don't forget to separate your terms with
|
133
|
-
commas
|
151
|
+
resourcing to nasty `eval` tricks. **Don't forget to separate your terms with
|
152
|
+
commas and freeze your hash constants!**
|
134
153
|
|
135
154
|
You've probably noticed that in order to use Ioughta in the top-level
|
136
155
|
namespace, we need to explicitly specify the `Object` receiver (just like we
|
137
156
|
need to do for `#const_set`). I didn't want to get too crazy with the
|
138
|
-
|
157
|
+
monkey-patching and/or method delegation. No such limitation exists when
|
139
158
|
including Ioughta in a module or class, thanks to the available context. Also,
|
140
|
-
if the `ioughta_const` and `ioughta_hash`
|
141
|
-
blame you), they're aliased as `iota_const` and `iota_hash`,
|
159
|
+
if the `ioughta_const` and `ioughta_hash` method names are too ugly for you (I
|
160
|
+
don't blame you), they're aliased as `iota_const` and `iota_hash`,
|
161
|
+
respectively.
|
142
162
|
|
143
163
|
Here is a very contrived and arbitrary example:
|
144
164
|
|
@@ -163,7 +183,7 @@ MyFileUtils.mask_and_shift(0644, :user) & MyFileUtils::EXECUTE # => 0
|
|
163
183
|
MyFileUtils.mask_and_shift(01777, :special) & MyFileUtils::TACKY # => 1
|
164
184
|
```
|
165
185
|
|
166
|
-
One note on the above: the lambda (or block) can take the key at the current
|
186
|
+
One note on the above: the lambda (or block) can take the "key" at the current
|
167
187
|
iteration as an optional second argument.
|
168
188
|
|
169
189
|
## Development
|
@@ -177,6 +197,10 @@ release a new version, update the version number in `version.rb`, and then run
|
|
177
197
|
git commits and tags, and push the `.gem` file to
|
178
198
|
[rubygems.org](https://rubygems.org).
|
179
199
|
|
200
|
+
## Trivium
|
201
|
+
|
202
|
+
Pronounced /aɪ ˈɔtə/, as in the English phrase "Why, I oughta...!"
|
203
|
+
|
180
204
|
## Contributing
|
181
205
|
|
182
206
|
Bug reports and pull requests are welcome on GitHub at
|
data/ioughta.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.authors = ['Mike Pastore']
|
11
11
|
spec.email = ['mike@oobak.org']
|
12
12
|
|
13
|
-
spec.summary = 'Helpers for defining
|
13
|
+
spec.summary = 'Helpers for defining sequences of constants in Ruby using a Go-like syntax'
|
14
14
|
spec.homepage = 'http://github.com/mwpastore/ioughta'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
data/lib/ioughta.rb
CHANGED
@@ -5,7 +5,7 @@ module Ioughta
|
|
5
5
|
def self.included(base)
|
6
6
|
class << base
|
7
7
|
def ioughta_const(*data, &block)
|
8
|
-
|
8
|
+
each_resolved_ipair(data, block) do |nom, val|
|
9
9
|
const_set(nom, val)
|
10
10
|
end
|
11
11
|
end
|
@@ -13,7 +13,7 @@ module Ioughta
|
|
13
13
|
alias_method :iota_const, :ioughta_const
|
14
14
|
|
15
15
|
def ioughta_hash(*data, &block)
|
16
|
-
|
16
|
+
each_resolved_ipair(data, block).to_h
|
17
17
|
end
|
18
18
|
|
19
19
|
alias_method :iota_hash, :ioughta_hash
|
@@ -23,38 +23,20 @@ module Ioughta
|
|
23
23
|
DEFAULT_LAMBDA = proc(&:itself)
|
24
24
|
SKIP_SYMBOL = :_
|
25
25
|
|
26
|
-
def
|
27
|
-
data = data.flatten
|
28
|
-
lam =
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
data.shift
|
33
|
-
else
|
34
|
-
DEFAULT_LAMBDA
|
35
|
-
end
|
36
|
-
|
37
|
-
(0..Float::INFINITY).lazy.each do |i|
|
38
|
-
if i % 2 != 0
|
39
|
-
if data[i].respond_to?(:call)
|
40
|
-
lam = data[i]
|
41
|
-
else
|
42
|
-
data.insert(i, lam)
|
43
|
-
end
|
44
|
-
elsif data[i].nil?
|
45
|
-
break
|
46
|
-
end
|
26
|
+
def each_ipair_with_index(data, block = nil)
|
27
|
+
data = data.to_a.flatten(1)
|
28
|
+
lam = (data.shift if data[0].respond_to?(:call)) || block || DEFAULT_LAMBDA
|
29
|
+
|
30
|
+
data.each_with_index do |nom, i, j = i.succ|
|
31
|
+
yield nom, data[j].respond_to?(:call) ? lam = data.slice!(j) : lam, i
|
47
32
|
end
|
48
|
-
data
|
49
33
|
end
|
50
34
|
|
51
|
-
def
|
52
|
-
return enum_for(__method__,
|
35
|
+
def each_resolved_ipair(*args)
|
36
|
+
return enum_for(__method__, *args) unless block_given?
|
53
37
|
|
54
|
-
|
55
|
-
|
56
|
-
next if nom == SKIP_SYMBOL
|
57
|
-
yield nom, val
|
38
|
+
each_ipair_with_index(*args) do |nom, lam, iota|
|
39
|
+
yield nom, lam.call(*[iota, nom].take(lam.arity.abs)) unless nom == SKIP_SYMBOL
|
58
40
|
end
|
59
41
|
end
|
60
42
|
end
|
data/lib/ioughta/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ioughta
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Pastore
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -93,5 +93,5 @@ rubyforge_project:
|
|
93
93
|
rubygems_version: 2.5.1
|
94
94
|
signing_key:
|
95
95
|
specification_version: 4
|
96
|
-
summary: Helpers for defining
|
96
|
+
summary: Helpers for defining sequences of constants in Ruby using a Go-like syntax
|
97
97
|
test_files: []
|