Picture of myself

Enumerable Methods:

#cycle

January the 15th in year 2015

I'll be talking about cycle, and not just any kind of cycle, but a method called cycle. This one is kind of tricky because it can easily end up in a never ending loop. I'll explain all about it later, but first let's look at it and admire its beauty for a second.

#cycle

Yeah, I know! Looks awesome!
Now let's look what it's capable of:

  array = [1,2,3,4]
  array.cycle{|x| puts x}

But wait! With this method, called as it is, you have to be really careful. It's so powerful that it can count to infinity. Indeed. Some serious stuff going on here. It's so powerful that it's almost like Chuck Norris, just that he did it twice, so it's not quite there yet.

So this makes an infinite loop, but luckily we can give it some arguments which would stand for number of cycles it would do.

  array = [1,2,3,4]
  array.cycle(2){|z| print z}

Output:

=> 12341234

Here we told it to make two cycles, so in fact we told it to make a bicycle. And it did! If you ever wondered how to make a bicycle, this is how to do it. As it turns out, it's not that hard.

Next we'll take a look how our friend works with method #next. Just so you know, #next gives you the following element. If you call it on integer 1, it would return you 2, just like if you call it on a string "a" it would give you "b".

  1.next
=> 2

  "a".next
=> "b"

And how can we use that with #cycle? If you have a variable pointing to an infinite loop it will always have a next item to return. Let's see:

  array = [1,2,3,4]
  my_loop = array.cycle
  my_loop.next
=> 1

  my_loop.next
=> 2

  my_loop.next
=> 3

  my_loop.next
=> 4

  my_loop.next
=> 1

  my_loop.next
=> 2

Pretty neat, right? Keep in mind that only works with #cycle. Let's see what happens if we do the same with #each.

  array = [1,2,3,4]
  my_loop = array.each
  my_loop.next
=> 1

  my_loop.next
=> 2

  my_loop.next
=> 3

  my_loop.next
=> 4

  my_loop.next
=> StopIteration: iteration reached an end
from (irb):7:in 'next'
from (irb):7
from C:/Ruby21-x64/bin/irb:11:in `<main>'

See? We get an error! This is because #each is not Chuck Norris and it has a limit to where it can count.

There's one more thing I'd want to point out. One might think that creating a variable (my_loop in our case) is pointless, because you can just call #next to array.cycle like so...

  array.cycle.next

... and he'd be wrong. Let's try it, just for the heck of it.

  array = [1,2,3,4]
      array.cycle.next
=> 1

  array.cycle.next
=> 1

  array.cycle.next
=> 1

Well, this looks more like #same than #next to me! And just that we are clear, #same is not a method, at least not one that I would know of.

Why this doesn't work with #next is beyond of scope of this post, so let's just except it and create a variable, and we can all live happily ever after.

...by Marko Anton Potocnik