Skip to content

Instantly share code, notes, and snippets.

@avdi
Created January 9, 2015 20:32
Show Gist options
  • Select an option

  • Save avdi/d9d92640e570fcba2988 to your computer and use it in GitHub Desktop.

Select an option

Save avdi/d9d92640e570fcba2988 to your computer and use it in GitHub Desktop.
Behold, the null enumerator.
e = loop
e # => #<Enumerator: main:loop>
e.next # => nil
e.next # => nil
e.peek # => nil
e.size # => Infinity
e.rewind
e.next # => nil
@avdi

avdi commented Jan 9, 2015

Copy link
Copy Markdown
Author

Like, I feel like this would make a good default argument in certain cases in order to avoid a special case.

@pnomolos

pnomolos commented Jan 9, 2015

Copy link
Copy Markdown

It's another way of writing while true do ... end, but whether or not that is useful is questionable at best.

@Peeja

Peeja commented Jan 9, 2015

Copy link
Copy Markdown

It's neat, but I'm not sure what I'd use it for. The other thing I'd call a null enumerator, [].each, I can come up with use cases for as null object. But the fact that loop is infinite and constant and gives you nil makes it seem pretty useless to me. I hope to be proven wrong, though. :)

@avdi

avdi commented Jan 9, 2015

Copy link
Copy Markdown
Author

It is not the same, because while does not give you an Enumerator.

@avdi

avdi commented Jan 9, 2015

Copy link
Copy Markdown
Author

Yeah, I'm just thinking that there may be certain scenarios where "always" makes sense instead of "never" as the default.

@AaronLasseigne

Copy link
Copy Markdown

Maybe there's some useful way to use it with zip.

> ('a'..'z').zip(loop).to_h
# => {"a"=>nil, "b"=>nil, "c"=>nil, "d"=>nil, "e"=>nil, "f"=>nil, "g"=>nil, "h"=>nil, "i"=>nil, "j"=>nil, "k"=>nil, "l"=>nil, "m"=>nil, "n"=>nil, "o"=>nil, "p"=>nil, "q"=>nil, "r"=>nil, "s"=>nil, "t"=>nil, "u"=>nil, "v"=>nil, "w"=>nil, "x"=>nil, "y"=>nil, "z"=>nil}

@Peeja

Peeja commented Jan 9, 2015

Copy link
Copy Markdown

It's certainly useful to have an infinite, constant enumerator, but I think the cases where you want it to be constantly nil are going to be rare.

Incidentally, what's the easiest way to make a constant enumerator, one that always returns, say 5? Off the top of my head, the best I've got is:

Enumerator.new do |y|
  loop do
    y.yield 5
  end
end

but that seems like way too much code for something so fundamental.

Actually, @avdi, loop breaks the consistency a bit because it doesn't yield anything to its block (that is, its block takes arity 0), and so its enumerator should return 0 things each time it's called. But since that doesn't quite make sense, it returns nil.

But if it did somehow return 0 things, this would be a much nicer way to create a constant enumerator:

loop.with_object(5)

Unfortunately, loop.with_object(5).first == [nil, 5].

@avdi

avdi commented Jan 9, 2015

Copy link
Copy Markdown
Author

Interestingly, @Peeja, at least next_values agrees with you:

e.next_values                   # => []

@AaronLasseigne

Copy link
Copy Markdown

@Peeja

[5].cycle

@avdi

avdi commented Jan 9, 2015

Copy link
Copy Markdown
Author

Nice.

@Peeja

Peeja commented Jan 12, 2015

Copy link
Copy Markdown

@AaronLasseigne Ooh, very nice.

@avdi That's interesting. It's a shame #with_object doesn't use use #next_values. I wonder if Ruby would accept a patch for it…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment