I am currently doing Test First programming and am stuck on the 06_performance monitor problem located at http://testfirst.org/live/learn_ruby/performance_monitor I found a similar thread on stackoverflow but I still am not understanding the problem. I am failing the last two tests on finding the average run time of multiple blocks. My code so far is:
def measure(i=1)
if i>1
i.times do
yield
end
else
x = Time.now
yield
elapsed_time = Time.now - x
end
end
I am very confused at what the test is trying to do. So far this is what I think I have to do:
I believe the task is to find how long certain blocks take to run. However, I am not sure exactly why this code is even working for the first few tests. And also I am having issues with knowing exactly what the yield statement is returning. I would really appreciate it if someone could walk me through the process of solving this problem so that I understand the solution.
Your method is mostly ok so far, except you don't need to branch out i == 1
from i > 1
– { 1.times { yield }
is functionally equivalent to just calling yield
.
yield
doesn't return anything on its own. It is a keyword that indicates the block given to the method should be called, and can optionally be fed variables that would in turn get passed to the block, e.g:
class String
def each_character_in_reverse_order
each_char.to_a.reverse_each do |char|
yield char
end
end
end
"hello".each_character_in_reverse_order do |c|
puts c.upcase
end
#=>
# O
# L
# L
# E
# H
In the case of the tests you've linked to, the return values of the blocks are complete inconsequential, as they are only interested in how long it takes to run the block. But as you can see in the example above, the yield
keyword can be embedded in a block of its own (reverse_each do ... end
), which means you can wrap other behavior around it each time the given block is called:
1.times do
start_time = Time.now
yield
elapsed = Time.now - start_time
end
In this case, you want to return values from the times do ... end
block so you can average together the runtimes of the given block, so you need to find a way to store these in an array, average them together, and return that average as the result of your measure
method. Keep in mind that you can average a single value to return that value, so you don't need different behavior for single runs vs. multiple runs. Hint - you can call n.times.map do ... end
to return an array directly from the times
block, without having to instantiate one explicitly.