Search code examples
crubyiteratorblocksyntactic-sugar

People keep telling me I'm writing "C style iterators" in ruby, and that I'm supposed to do it this other way, without the i++ thing


The details here aren't important, it's just an example, all that matters is the i=0, i+=1 action

def sortAndIndex
  #sorting keys
  @disco = Hash[@disco.sort]

  #basic setup for both input types
  @years = @disco.keys
  @albums = @disco.values
  sum = @years.count

  #setup for "albums" input
  @allalbums = []
  i = 0
  sum.times do
  thatyear = @years[i] + ", " + @albums[i]
  @allalbums << thatyear
  i += 1
 end
end

Now this does work, as should any other "i++" type ("C-style") iterator in ruby or most other languages. However, I keep hearing that ruby has this better way to do this, where basically I'd be passing a second parameter variable other than, here, 'a'.

What modifications would I make to do this and are there multiple "shortcuts" which ruby has involving these sorts of i++ ary[i] iterator problems?


Solution

  • Yes, you should do things the "Ruby way" and forget about indexing. Why? Because it is idiomatic and looks nicer. You pass in a block of code to be executed upon each element of a collection. How the elements are stored, in what order, if they can be indexed into, is all irrelevant.

    # nice, eh?
    some_array.each do |elem|
      some_action(elem)
    end
    

    If you need an index counter (you don't in your example) use each_with_index instead.

    Also note that the concept of blocks is important in Ruby outside of iterating a collection. What you have there is... odd... and you should listen to them, but many methods take blocks as arguments (or optional arguments) which do not return collections which can be indexed. For example, File.open takes a block and, if supplied, closes the file for you when the block returns

    Also, another thing to note; your naming conventions are atypical for Ruby. Rubyists use lowercase function and variable names with underscores_between_words. Best to stick with the community here.