I'm building the Test-First-Teaching performance_monitor and can get to the fifth test but then it fails.
Why is my block only running once?
This is my code:
require "time"
t = Time.now
def measure x=0
start = Time.now
yield x
endt = Time.now - start
end
measure(4){ |x| x.times do Time.now - t end}
This is the error:
*Error____
Performance Monitor
takes about 0 seconds to run an empty block
takes exactly 0 seconds to run an empty block (with stubs)
takes about 1 second to run a block that sleeps for 1 second
takes exactly 1 second to run a block that sleeps for 1 second (with stubs)
runs a block N times (FAILED - 1)
Failures:
1) Performance Monitor runs a block N times
Failure/Error: n.should == 4
expected: 4
got: 1 (using ==)
Think about it like this: Your measure
method is the one that's in charge of making sure the block that gets passed to it is run the correct number of times. So the block you pass to measure
should only include the code that should be run in a single iteration.
For a bare-bones example (theme shamelessly ripped from Gary Bernhardt's "WAT" talk):
def repeat_x_times(x)
# This runs the passed block x times:
x.times do
yield
end
end
repeat_x_times(16) do
# This is what should happen in a single iteration:
puts 0.0 / 0.0
end
puts 'Batman!'
The other cool thing about blocks is that you can always access the variables in the same scope as the block (usually local variables), regardless of where the yield happens:
i = 3
4.times {i += 1} # We can still get to i!
puts i # Prints "7"
Combining the two concepts for a slightly more involved example:
array = [3, 6, 9, 12, 15]
sum = 0
array.each do |item|
# In the first iteration, item is 3; in the second it's 6, and so on:
sum += item
end
puts sum
Now, I know I haven't answered your question directly, but it sounds like you're learning Ruby, so hopefully this is more useful than a cut-n-paste... Anyway, just play around with this until you get it, and pretty soon you'll be wishing all languages had such a useful feature!