ioughta 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0c12c98fe08970c112e895a81c1a235bfc89c34b
4
- data.tar.gz: 69c50f6794139a6ccb84c51630a418ef33381eb0
3
+ metadata.gz: 7918cd422602dfb4b8d10a0a22a41ecd7385d092
4
+ data.tar.gz: 529732cd9cfc9f3e8dc9f11422aaaa43dea9a35e
5
5
  SHA512:
6
- metadata.gz: d8ee63a12106312f5701f9ddc2b7c2ded8b77e8febcb19a16ee94205de2ad4fcf290f75da6b8b1448e92e0a3ebfec5b977d01f3e395e83853b969464d384d6dc
7
- data.tar.gz: 1a9382fdfdf9c4a57bdb58eb12e3f373d7db4e42e93922cb85b2e9174ccffb86e8de3341bb6b5a78e59bf042da657d052a41514ba4d8589f44fca975fc9e426b
6
+ metadata.gz: 9c64d851fb46da155fb80c475ba9ae391cb3deee69106f196e35a5c9c99a45b275ddc4d6f8197cdd98164b2614a44cc58dac40d9f2d33cd2eb3a0204711257a7
7
+ data.tar.gz: c7ac30fba3192205a238ac82b4fb3833a523b0f7c063611ab5bee3ad3e1baaf85d4e43d8434ab09a26ea401542edaf23710753a52ea2a037189c2eb55e52958b
data/README.md CHANGED
@@ -3,28 +3,36 @@
3
3
  [![Build Status](https://travis-ci.org/mwpastore/ioughta.svg?branch=master)](https://travis-ci.org/mwpastore/ioughta)
4
4
  [![Gem Version](https://badge.fury.io/rb/ioughta.svg)](https://badge.fury.io/rb/ioughta)
5
5
 
6
- Helpers for defining Go-like constants and hashes in Ruby using iota.
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
- Here's an example, written in Go:
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 // 1 << 0 which is 00000001
20
- IgChocolate // 1 << 1 which is 00000010
21
- IgNuts // 1 << 2 which is 00000100
22
- IgStrawberries // 1 << 3 which is 00001000
23
- IgShellfish // 1 << 4 which is 00010000
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
- Here it is in Ruby, using ioughta:
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.ioughta_hash(->(i) { 1 << i }, %i[
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[:strawberries] # => 8
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 (`0`) and increments for
80
- each constant. The default lambda is simply `:itself`, so you can very easily
81
- create a sequence of constants with consecutive integer values:
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 to generate future
101
- values from the iterator. In Go parlance, this is (apparently) known as
102
- *implicit repetition of the last non-empty expression list*. You can redefine
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, proc(&:itself) # restore the default behavior (6 => 6)
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.ioughta_const ->(i) { 1 << (10 * i) }, %i[_ KB MB GB TB PB EB ZB YB]
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| 1 << (10 * i) }.freeze
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
- monkeypatching and/or dynamic dispatch. No such limitation exists when
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` methods are too ugly for you (I don't
141
- blame you), they're aliased as `iota_const` and `iota_hash`, respectively.
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 Go-like constants and hashes using iota'
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
- each_resolved_pair(pair(data, &block)) do |nom, val|
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
- each_resolved_pair(pair(data, &block)).to_h
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 pair(data, &block)
27
- data = data.flatten
28
- lam =
29
- if block
30
- block
31
- elsif data.first.respond_to?(:call)
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 each_resolved_pair(data)
52
- return enum_for(__method__, data) { data.length / 2 } unless block_given?
35
+ def each_resolved_ipair(*args)
36
+ return enum_for(__method__, *args) unless block_given?
53
37
 
54
- data.each_slice(2).with_index do |(nom, lam), iota|
55
- val = lam.call(*[iota, nom].take(lam.arity.abs))
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
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: false
2
2
  module Ioughta
3
- VERSION = '0.2.1'.freeze
3
+ VERSION = '0.3.0'.freeze
4
4
  end
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.2.1
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-14 00:00:00.000000000 Z
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 Go-like constants and hashes using iota
96
+ summary: Helpers for defining sequences of constants in Ruby using a Go-like syntax
97
97
  test_files: []