4
\$\begingroup\$

Is there a better way to time the functions and print the result and function name dynamically?

package project_euler
object Timers extends App{
 def time[R](f: => R): Unit = {
 val t0 = System.nanoTime()
 val r = f
 val t1 = System.nanoTime()
 val t = (t1-t0)/1000
 println(s"The result is: $r time taken $t ms ")
 // print also the name of the function f**
 }
 /*
 * Problem 1 project Euler
 * If we list all the natural numbers below 10 that are multiples of 3 or 5,
 * we get 3, 5, 6 and 9.
 * The sum of these multiples is 23.
 * Find the sum of all the multiples of 3 or 5 below 1000.
 * */
 //functional implementation 
 def func = (0 until 1000).filter(x => x % 3 ==0 || x % 5 ==0).sum
 //imperative implementation
 def imper = {
 var i,sum = 0
 while (i < 1000) {
 if( i % 3 ==0 || i % 5 ==0)
 sum +=i
 i+=1 //increase counter
 }
 sum
 } 
 time (func)
 time (imper)
 }
200_success
146k22 gold badges190 silver badges478 bronze badges
asked Jul 18, 2014 at 18:08
\$\endgroup\$
0

2 Answers 2

6
\$\begingroup\$

So, I pasted your code into my IDE and ran it in the debugger, and there isn't really any way to do exactly what you want to do. The function object doesn't appear to have any knowledge of anything other than how to call it.

Your best bet seems to be to modify the timing function to something like this:

 def time[R](f: => R, name: String): Unit = {
 val t0 = System.nanoTime()
 val r = f
 val t1 = System.nanoTime()
 val t = (t1-t0)/1000
 println(s"The result of $name is: $r time taken $t ms ")
 }

And then your call would be something like this:

 time (func, "func")

In a larger app, if you needed to pass around functions with their name, you could create a small object such as:

class Caller[R](f: => R, name: String) {
 def time(): Unit = {
 val t0 = System.nanoTime()
 val r = f
 val t1 = System.nanoTime()
 val t = (t1-t0)/1000
 println(s"The result of $name is: $r time taken $t ms ")
 }
}

Create it like so:

val a = new Caller(func, "func")

And call it like so:

a.time()
answered Jul 18, 2014 at 20:25
\$\endgroup\$
1
  • \$\begingroup\$ Another way is to return a tuple from the measured function f i.e (result,functionName) so i would not alter the time function. Again this is not elegant enough though. I also looked at Thread.currentThread().getStackTrace()(1).getMethodName() In order to get the name of the function from the stack trace but scala erases the name of f to function0. So i guess there is no other clean way of extracting the functions name.. \$\endgroup\$ Commented Aug 5, 2014 at 23:23
1
\$\begingroup\$

There is a new feature in Scala called "macros" which does exactly what you want. It is basically code to manipulate code. I have not used it yet, so I can't give you an example.

It is an advanced topic and it might still be classified as an experimental feature. So you are probably better avoiding it for now. You can just make a Map[String, => R] for the time being.

answered Jul 18, 2014 at 20:34
\$\endgroup\$
2
  • \$\begingroup\$ @ toto2 i don't see how a Map[String,=> R] is any different it's still a "static" way of printing the name of the function passed. I'm aware of scala's macro system (metaprogramming) but i haven't used it yet \$\endgroup\$ Commented Jul 18, 2014 at 20:49
  • \$\begingroup\$ It's basically the same, but I think it would be cleaner to put everything in a map and then create some function to process that map. \$\endgroup\$ Commented Jul 18, 2014 at 20:53

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.