From: Ben Giddings Date: 2007-10-25T06:14:12+09:00 Subject: Re: .each do |foo, bar| what does bar do? On 04:50 Thu 25 Oct , Thufir wrote: > "code_words.each do |real, code| > idea.gsub!( real, code ) > end > You see the each method? The each method is all over in Ruby. It's > available for Arrays, Hashes, even Strings. Here, our code_words > dictionary is kept in a Hash. This each method will hurry through all > the pairs of the Hash, one dangerous word matched with its code word, > handing each pair to the gsub! method for the actual replacement." > > from page 33 of whys-poignant-guide-to-ruby.pdf > > > > Is this similar to nested for statements? I don't think so. In the > first line, why are both "real" and "code" part of the interation? > >From my understanding of a hash, you can iterate through the keys only > and then find the corresponding bit of the hash. > > Why would this fail: > > code_words.each do |real| > idea.gsub!( real, code ) > end What's happening in the first version of the code is that "real" and "code" are being assigned from within the "each" method. At some point within each there's some code that essentially looks like: "yield(current_hash_key, current_hash_value)". When that code is run, ruby assigns the variable (in your scope) real to the value of "current_hash_key" within the "each" method, and it assigns the variable "code" to the value of "current_hash_value". Because "yield" has two arguments, the block you pass each should have two parameters, which it does. If you used this instead: code_words.each do |foo| ... end Foo would be assigned an array containing both things sent by "yield", i.e. foo[0] would be the same as real, and foo[1] would be the same as code. The key thing here is that not every "each" is the same. Some have a "yield" that tries to send out one value (like the "each" for arrays), some pass multiple values (like the "each" for hashes). You need to know how many variables your "each" wants to assign in a block. In your example: code_words.each do |real| idea.gsub!( real, code ) end real would get assigned, but "code" wouldn't have been assigned, so Ruby wouldn't know what "code" was and would complain. Ben