enumerator_generate 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []