Question

I'm working on some homework problems for a ruby course and I've been having some trouble with my answer. Basically I need to build a program that can satisfy these conditions:

describe "reverser" do
 it "reverses the string returned by the default block" do
  result = reverser do
    "hello"
  end
  result.should == "olleh"
 end

 it "reverses each word in the string returned by the default block" do
  result = reverser do
    "hello dolly"
  end
  result.should == "olleh yllod"
 end
end

I puzzled together some code that I feel should satisfy these conditions:

reverser = Proc.new do |string|

 words = string.split(/\b/)

 answer = ''

 i = 0
 while i < words.count
     answer = answer + words[i].reverse
     i += 1
 end
 answer
end


def reverser
 yield

end

Yet when I run the rake, my error tells me I have failed the first condition.

expected: "olleh"
got: "hello"

Is there something I'm missing? Do I just not have a proper understanding of procs?

This question has been asked in some form already by a member named pete and answered quite well by another user named mind.blank. This is the source:

Beginner RSpec: Need help writing Ruby code to pass RSpec tests (Silly Blocks exercise).

mind.blank's code was straightforward and worked properly, but I don't just want to copy it without understanding why mine doesn't work. Thanks in advance for any help.

No correct solution

OTHER TIPS

So - what you've got there is a local variable named "reverser" and a method named "reverser" (which is going to "shadow" the reverser local)

Your code is never executing.

So - what you want to do is ... take the result of the yield and do the reverse operation on that. (Leaving aside how bizarre that requirement is for a moment.)

def reverser
  string = yield
  # ... all of your reverser code ...
end

Now circling back around - that's a bizarre way to use a block. A block is for passing additional execution to a method, not for passing argument to it. So if you wanted to say, have a callback executed for each character in reverser (in reverse?) that would be the proper use of yield.

Besides, Ruby already has a String#reverse method - so the easiest possible thing to do to get your tests to pass is something like.

def reverser
  (yield).split(/\b/).map(&:reverse).join
end

Your reverser proc does work, if you say reverser.call('abc') (or reverser['abc'] or reverser.('abc')) then you will get the expected 'cba' back.

The problem is that your test isn't using your reverser proc, it is using your reverser method. This is a call to the reverser method with a block:

result = reverser do
  "hello"
end

but the reverser method doesn't do anything interesting, it just yields to the block:

def reverser
  yield
end

so result ends up being the block's value and that's 'hello'.

Either test the proc:

it "reverses the string returned by the default block" do
  result = reverser['hello']
  result.should == "olleh"
end

or move the proc's guts into the reverser method and test that:

def reverser
  string = yield
  words  = string.split(/\b/)
  answer = ''

  i = 0
  while i < words.count
    answer = answer + words[i].reverse
    i += 1
  end
  answer
end

There are better ways to write this code (such as words.map(&:reverse).join instead of the while look) but your reversing logic works, you just have to make sure you call the right version.

This code will reverse strings given to the method as a block

def reverser
    # yield is the string given in the block
    words = yield.split(' ')
    final = []
    words.each do |word|
        final.push(word.reverse)
    end
    final.join(' ')
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top