Created
July 4, 2014 16:30
-
-
Save batizhevsky/000e0406e22dc81884b6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Co-routines are severely under-utilized in Ruby. | |
There's a truly magical line you can add to the top of a function that yields a bunch of values, | |
`return to_enum(__callee__) unless block_given?` | |
which makes the function return an Enumerator enumerating its values if you don't explicitly pass it a block. | |
As a simple example, consider this, | |
```ruby | |
def numbers | |
return to_enum(__callee__) unless block_given? | |
yield 1 | |
yield 2 | |
yield 3 | |
end | |
``` | |
You will now have `numbers.to_a == [1, 2, 3]`. | |
This allows you to do some really sexy stuff, though it may not be obvious at first. Imagine you're interfacing with an external API (maybe for fetching Reddit posts). The API allows you to check whether there's another post (has_next_post?) and if so, to fetch it (next_post). | |
Normally, you might end up with various methods for fetching various numbers of posts according to different criteria. You might need to fetch the first 10 posts within the last week, etc. But using this trick you only need one basic method: | |
```ruby | |
def all_posts | |
return to_enum(__callee__) unless block_given? | |
while api.has_next_post? | |
yield api.next_post | |
end | |
end | |
``` | |
For fetching the first 10 posts within the last week you can now do, | |
`all_posts.lazy.take_while{ |p| p.date <= 1.week.ago }.take(10)` | |
The magic is that you can verify that this will only make the number of API calls that are actually required. The execution of the method pauses and ends when the final take gets everything it needs. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment