enumerator_generate 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9570b3287b1910c7a5fa6fddae5f3706d40ee745885b226da236a5e65223c70a
4
+ data.tar.gz: c99e8abce49b85df5f03007c033cfc90a429fa3a61ce88edafebd8112e53f9cc
5
+ SHA512:
6
+ metadata.gz: cdc400176f0915f01022f093660442a7248d61c7e4882a0b692db5215d9aca5013651d6b66ff7c5a67b110332c0bbd568154ed507a6ca5c4a7cbf08b03d28d24
7
+ data.tar.gz: d573ce12a0bb2ce869052759de7202abc98299035c695a7cda942aa8ce19d31732c30b665babdf0b43f10f0a47d426d0785bdf634fd66193791cf0f9da934027
@@ -0,0 +1,48 @@
1
+ # `Enumerator#generate`
2
+
3
+ This is an alternative to [`Object#enumerate`](https://github.com/zverok/object_enumerate) Ruby language core proposal. Goal is the same: generating enumerators which can idiomatically replace (most of) `while` and `loop` cycles.
4
+
5
+ After some experiments, it turns out that "start from initial value, and continue with this block" (like `Object#enumerate` does) is not the only important use case. "Just enumerate with this block" is equally important, and `Enumerator#generate` supports this case finely. Also, the call sequence seems to be less confusing, it is pretty straight: `Enumerator#generate` generates an enumerator from block and optional initial value.
6
+
7
+ ## Synopsys
8
+
9
+ `Enumerator#generate` takes a block and optional initial value, and generates (infinite) enumerator by applying the block to result of previous iteration. If initial value is not passed, first block receives no arguments.
10
+
11
+ ## Examples of usage
12
+
13
+ ### With initial value
14
+
15
+ ```ruby
16
+ # Infinite sequence
17
+ p Enumerator.generate(1, &:succ).take(5)
18
+ # => [1, 2, 3, 4, 5]
19
+
20
+ # Easy Fibonacci
21
+ p Enumerator.generate([0, 1]) { |f0, f1| [f1, f0 + f1] }.take(10).map(&:first)
22
+ #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
23
+
24
+ require 'date'
25
+
26
+ # Find next Tuesday
27
+ p Enumerator.generate(Date.today, &:succ).detect { |d| d.wday == 2 }
28
+ # => #<Date: 2018-05-22 ((2458261j,0s,0n),+0s,2299161j)>
29
+ ```
30
+ (Other examples from [`Object#enumerate`](https://github.com/zverok/object_enumerate) are easily translated, too.)
31
+
32
+ ### Without initial value
33
+
34
+ ```ruby
35
+ # Random search
36
+ target = 7
37
+ p Enumerator.generate { rand(10) }.take_while { |i| i != target }.to_a
38
+ # => [0, 6, 3, 5,....]
39
+
40
+ # External while condition
41
+ require 'strscan'
42
+ scanner = StringScanner.new('7+38/6')
43
+ p Enumerator.generate { scanner.scan(%r{\d+|[-+*/]}) }.take_while { !scanner.eos? }.to_a
44
+ # => ["7", "+", "38", "/"]
45
+
46
+ # Potential message loop system:
47
+ Enumerator.generate { Message.receive }.take_while { |msg| msg != :exit }
48
+ ```
@@ -0,0 +1,46 @@
1
+ require_relative 'lib/enumerator_generate'
2
+ require 'pp'
3
+
4
+ # Infinite sequence
5
+ p Enumerator.generate(1, &:succ).take(5)
6
+
7
+ # Easy Fibonacci
8
+ p Enumerator.generate([0, 1]) { |f0, f1| [f1, f0 + f1] }.take(10).map(&:first)
9
+
10
+ require 'date'
11
+
12
+ # Find next Tuesday
13
+ p Enumerator.generate(Date.today, &:succ).detect { |d| d.wday == 2 }
14
+
15
+ require 'nokogiri'
16
+ require 'open-uri'
17
+
18
+ # Find some element on page, then make list of all parents
19
+ p Nokogiri::HTML(open('https://www.ruby-lang.org/en/'))
20
+ .at('a:contains("Ruby 2.2.10 Released")')
21
+ .yield_self { |node| Enumerator.generate(node, &:parent) } # Enumerator#generate is a bit wordy in chains
22
+ .take_while { |node| node.respond_to?(:parent) }
23
+ .map(&:name)
24
+
25
+ require 'octokit'
26
+
27
+ Octokit.stargazers('rails/rails')
28
+ # ^ this method returned just an array, but have set `.last_response` to full response, with data
29
+ # and pagination. So now we can do this:
30
+ p Enumerator.generate(Octokit.last_response) { |response| response.rels[:next].get } # pagination: `get` fetches next Response
31
+ .first(3) # take just 3 pages of stargazers
32
+ .flat_map(&:data) # data is parsed response content (stargazers themselves)
33
+ .map { |h| h[:login] }
34
+
35
+ # No initial value: random search
36
+ target = 7
37
+ p Enumerator.generate { rand(10) }.take_while { |i| i != target }.to_a
38
+
39
+ # No initial value: external while condition
40
+ require 'strscan'
41
+ scanner = StringScanner.new('7+38/6')
42
+ p Enumerator.generate { scanner.scan(%r{\d+|[-+*/]}) }.take_while { !scanner.eos? }.to_a
43
+
44
+
45
+ # Potential message loop system:
46
+ # Enumerator.generate { Message.receive }.take_while { |msg| msg != :exit }
@@ -0,0 +1,16 @@
1
+ class Enumerator
2
+ NOVALUE = Object.new.freeze
3
+
4
+ def self.generate(initial = NOVALUE)
5
+ raise ArgumentError, "No block given" unless block_given?
6
+ Enumerator.new do |y|
7
+ val = initial == NOVALUE ? yield() : initial
8
+ y << val
9
+
10
+ loop do
11
+ val = yield(val)
12
+ y << val
13
+ end
14
+ end
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enumerator_generate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Victor Shepelev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-05-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubygems-tasks
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: " This is just a showcase gem to support language core proposal.\n"
42
+ email: zverok.offline@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - README.md
48
+ - examples.rb
49
+ - lib/enumerator_generate.rb
50
+ homepage: https://github.com/zverok/enumerator_generate
51
+ licenses:
52
+ - MIT
53
+ metadata: {}
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 2.2.0
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 2.7.4
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: 'Enumerator#generate: Simple infinite enumerators'
74
+ test_files: []