How do Enumerators work in Ruby 1.9.1?
Here's a plain ruby enumerator that uses Fibers and should pretty much behave like the original:
class MyEnumerator
include Enumerable
def initialize(obj, iterator_method)
@f = Fiber.new do
obj.send(iterator_method) do |*args|
Fiber.yield(*args)
end
raise StopIteration
end
end
def next
@f.resume
end
def each
loop do
yield self.next
end
rescue StopIteration
self
end
end
And in case anyone is feeling uneasy about using exceptions for control flow: The real Enumerator raises StopIteration at the end, too, so I just emulated the original behaviour.
Usage:
>> enum = MyEnumerator.new([1,2,3,4], :each_with_index)
=> #<MyEnumerator:0x9d184f0 @f=#<Fiber:0x9d184dc>
>> enum.next
=> [1, 0]
>> enum.next
=> [2, 1]
>> enum.to_a
=> [[3, 2], [4, 3]]
Equivalent of Ruby Enumerable.collect that returns an Enumerable?
Ruby 2.0 introduced Enumerable#lazy
which allows one to chain map
, select
, etc..., and only generate the final results at the end with to_a
, first
, etc... You can use it in any Ruby version with require 'backports/2.0.0/enumerable/lazy'
.
require 'backports/2.0.0/enumerable/lazy'
names = (1..Float::INFINITY).lazy.map{|i| "hacker_" + String(i) }
names.first # => 'hacker_1'
Otherwise, you can use Enumerator.new { with_a_block }
. It's new in Ruby 1.9, so require 'backports/1.9.1/enumerator/new'
if you need it in Ruby 1.8.x.
As per your example, the following will not create an intermediate array and will only construct the needed strings:
require 'backports/1.9.1/enumerator/new'
def find_me_an_awesome_username
awesome_names = Enumerator.new do |y|
(1..1000000).each {|i| y.yield "hacker_" + String(i) }
end
awesome_names.find {|n| not stackoverflow.userexists(n) }
end
You can even replace the 100000 by 1.0/0 (i.e. Infinity), if you want.
To answer your comment, if you are always mapping your values one to one, you could have something like:
module Enumerable
def lazy_each
Enumerator.new do |yielder|
each do |value|
yielder.yield(yield value)
end
end
end
end
awesome_names = (1..100000).lazy_each{|i| "hacker_#{i}"}
Why Ruby's array of 1000 hashes' key and value pairs are always in a particular order?
The layout of the hash is deterministic. So for a particular version of ruby, if you always add/remove the keys of a hash in the same order, the layout of the hash will be the same. This means iterating over the hashes in your array will have the keys all in the same order.
Segmentation fault' when executing Enumerator#next in rails console
I don't see an issue for this reported against Ubuntu, but I do see one for OS X Lion. You might consider figuring out where exactly to report the issue against 1.9.2 and try to see if anyone in the community there can give you more guidance on how to get a bug report (a) verified as an actual bug and not caused by something else, and (b) where and how to file the bug if it does get verified.
I don't believe you're supposed to create issues directly in the backport page, but at least for reference here are the list of issues on the 1.9.2 backport list.
- https://bugs.ruby-lang.org/projects/ruby-192/issues?set_filter=1
Ruby 1.9.1 standard library documentation online anywhere?
Try this:
http://yardoc.org/docs/ruby-stdlib
and this:
http://yardoc.org/docs/ruby-core
Iterate over an infinite sequence in Ruby
In Ruby >= 1.9, you can create an Enumerator object that yields whatever sequence you like. Here's one that yields an infinite sequence of integers:
#!/usr/bin/ruby1.9
sequence = Enumerator.new do |yielder|
number = 0
loop do
number += 1
yielder.yield number
end
end
5.times do
puts sequence.next
end
# => 1
# => 2
# => 3
# => 4
# => 5
Or:
sequence.each do |i|
puts i
break if i >= 5
end
Or:
sequence.take(5).each { |i| puts i }
Programming Ruby 1.9 (aka "The Pickaxe Book"), 3rd. ed., p. 83, has an example of an Enumerator for triangular numbers. It should be easy to modify the Enumerator above to generate triangular numbers. I'd do it here, but that would reproduce the example verbatim, probably more than "fair use" allows.
Related Topics
Instance Variables Inheritance
Ip Range to Cidr in Ruby/Rails
Open a File Case-Insensitively in Ruby Under Linux
How to Extend a Class from an Initializer and Have It Reload in Development Environment
What Exactly Is a Gem Native Extension
Before(:Each) for All Tests Except One
How to Ensure a Rake Task Only Running a Process at a Time
When Installing Gems "Error: Permission Denied Rb_Sysopen" Arch Linux
Ruby: Controlling Printing in Scientific Notation
Finding the Difference Between Strings in Ruby
Accessing Headers from Sinatra