JD JD wrote in post #1130915:
>
> def reverse
>   sentence=yield.split
>
>   sentence.map do |word|
>     word.reverse!
>   end
>
>   sentence.join(" ")
> end
>
> However, I am still semi lost.  I don't understand the difference
> between .map and .each.  All I know is using .each doesn't seem to make
> the thing pass.  Could someone explain me the difference between the
> two?

The difference between #map and #each is what they return.  #map is used 
to create a new array whose elements are mapped from the original array; 
e.g:

  a1 = [1, 2, 3]
  a2 = a1.map {|x| x * 2 }
  p a1 #=> [1, 2, 3]
  p a2 #=> [2, 4, 6]

There's a version called #map! which updates the array; e.g:

  a1 = [1, 2, 3]
  a1.map! {|x| x * 2 }
  p a1 #=> [2, 4, 6]

While #each is used to iterate through the elements without mapping 
them, and usually you wouldn't modify the array from inside the block; 
e.g:

  a3 = [1, 2, 3]
  a3.each {|x| puts x }

Your solution is a valid mixture, even though you used #map instead of 
#each; there are two or three alternatives you could do if you want to 
make your code look a bit more "correct":

1) use #each ; this one works* because you're using String#reverse! to 
modify each element of the 'sentence' array, without changing the array 
itself.

  def reverse
    sentence = yield.split
    sentence.each do |word|
      word.reverse!
    end
    sentence.join(" ")
  end

* at least, it works for me, in Ruby 1.9.1 and up.

2) use the return value from #map ; this works because you're creating a 
second array whose elements are mapped from the first array.

  def reverse
    sentence = yield.split
    backwrds = sentence.map do |word|
      word.reverse
    end
    backwrds.join(" ")
  end

3) similar to #2, but use #map! so you don't need a second array 
variable.

  def reverse
    sentence = yield.split
    sentence.map! do |word|
      word.reverse
    end
    sentence.join(" ")
  end


> Also, I am still really confused about this.  You are correct,  tamouse
> m, this was to introduce blocks.  However, this set up really confuses
> me.  How does yield take in the "hello world"?  I find it really
> confusing.  Could someone explain this set up a little more?  It appears
> it is blocks, but I am used to using blocks in a different context and I
> find this set up/thing really confusing.  Although, I will be honest,
> I'm not super familiar with blocks really.  I could probably use a good
> refresher (or maybe even a site that explains them if that would be
> easier).

I can give you a slightly more complicated example, which might help; it 
assumes you have defined any of the #reverse methods listed above:

  reverse do
    File.open('some_words.txt','r'){|f| f.read }
  end

When #reverse yields, the block reads the words from a text file.  If 
you invoked 'yield' twice, it would read the file twice.  There's no 
limit to the complexity you could add inside that block; the reason it's 
useful is that #reverse doesn't care how complex the block is, once it 
works it will keep on working.

If you're familiar with javascript's habit of passing functions as 
objects (or the concept of Lambda functions in general) you could even 
do this:

  get_words = lambda {
    words = File.open('some_words.txt','r'){|f| f.read }
    # blah blah, extra processing
    return words
  }

  obfuscated_words = reverse &get_words

I added a redundant 'return' in there, because sometimes people like 
that sort of thing.  It's just to demonstrate that 'get_words' is a 
fully-fledged Lambda function, which you can pass as the block parameter 
to #reverse.

-- 
Posted via http://www.ruby-forum.com/.