1

*Apologies if the question's wording is confusing. I didn't know exactly how to ask it.

How can I do something like this?

def track_time(function, input)
    beg = Time.now

    function(input)

    end = Time.now
    end - beg
end

And then pass it a function and a value for that function to use.

def double(value)
    value + value
end

p track_time(double, 5)

The goal is to create something repeatable so I can track how long different functions take to complete.

tim_xyz
  • 11,573
  • 17
  • 52
  • 97

3 Answers3

3

First you can not use 'end' as a variable name.

As for your question, I agree with Mladen Jablanovićyou that for this use case a block is better, but since you specifically asked about passing a method as a parameter to another method, you can use the 'send' method:

def track_time method, value
  begin_time = Time.now
  send method, value
  end_time = Time.now
  end_time - begin_time
end

def double(value)
    value + value
end

p trcak_time(:double, 5)
kirlev
  • 680
  • 1
  • 7
  • 17
3

Unfortunately, methods in Ruby are not first-class objects, so they can't be directly passed as arguments. You can pass a name of the method (usually passed as symbol) instead, as other answers suggest.

But the idiomatic way to achieve what you are aiming for are blocks:

def track_time
  start = Time.now

  yield

  finish = Time.now
  finish - start
end

track_time do
  double(5)
end
#=> 6.127e-06
Community
  • 1
  • 1
Mladen Jablanović
  • 43,461
  • 10
  • 90
  • 113
  • Is this preferable in "Ruby style" over using the "send" method? – tim_xyz Jun 04 '16 at 15:46
  • 1
    I personally would favor this style, as Mladen mentioned it is idiomatic Ruby. You could always write a one liner ``track_time { double(5) }`` if it is not too long. Not to mention, what would you do if you needed multiple arguments in another method? (sure you could use a splat operator but using a block seems the right way to go). – Nabeel Jun 04 '16 at 16:15
  • 1
    @pandaman `send` is primarily used to invoke methods dynamically, i.e. when you don't know in advance which method you need to invoke - for example, if actual method depends on user's input. Also, with block approach, you can measure duration of arbitrary code sequence, not only a single method call. – Mladen Jablanović Jun 04 '16 at 17:43
2

Remember that end is a reserved word in Ruby (I suspect it was for illustration purposes anyhow).

You could pass in the string/symbol of the function name instead.

def track_time(function, input)
  start = Time.now

  method(function).call(input)

  finish = Time.now
  finish - start
end

def double(value)
  value + value
end

track_time('double', 5)
=> 6.127e-06
Nabeel
  • 2,272
  • 1
  • 11
  • 14