I would like to get the name of the current method programmatically (from within this method).
In Java I would do it via throwing exception and search in the stack trace.
But this is expensive (in terms of time, not in LoC). There will be hundreds of such calls.
Is there eventually a more effective solution for Scala?
Regards,
Eugen Labun
Perhaps we should start a new group / list, Scala-Dynamic,
for all the refugees from those other languages...
Randall Schulz
this is still an improvement.
On 14 Mar 2011 13:14, "Eugen Labun" <la...@gmx.net> wrote:
>
> Hi all,
>
> I would like to get the name of the current method programmatically (from within this method).
>
Can I ask why?
If it's not for exception reporting, then there may be a better way...
--
Jim Powers
It's a legit reason and it comes up all the time for me: I end up with
lots of code which for one reason or another looks like
val foo = something("foo", ...)
Clearly in these contexts it would be useful to be able to refer to the
name of what you are. Just because one of the duplications is in quotes
doesn't mean it's not pure duplication.
If you ponder the problem a moment, it is odd that we have this first
class construct "this" to refer to "the current class" but nothing for
the current method. The method is (already, but far more so in java 7)
a discrete unit of functionality. Given a way to refer to the current
method one could do interesting things like...
thisMethod.recurse(5) // immunized against name changes
thisMethod.name
thisMethod.alternatives
... your idea here!
Correction:
Grr. getting the "correct" arity (including "splats" and block
arguments) is not straight-forward.
Enough on Ruby, back to Scala.
--
Jim Powers
This is on the roadmap right? ;-)
--
Jim Powers
And yeah, it would be very interesting to have "thisMethod".
Where can I read more about new features of methods in Java 7? (Haven't heard anything about what
you've mentioned.)
I will look into it.
(This will surely need some time.)
Found: that should be 'MethodHandle'
> On 3/14/11 6:50 AM, Eugen Labun wrote:
> > I develop a parsing library. The idea is to automatically name each
> > parser rule according to the name of the defining method to
> > (automatically) produce better debugging and error mesages.
>
> It's a legit reason and it comes up all the time for me: I end up with
> lots of code which for one reason or another looks like
>
> val foo = something("foo", ...)
>
> Clearly in these contexts it would be useful to be able to refer to the
> name of what you are. Just because one of the duplications is in quotes
> doesn't mean it's not pure duplication.
This is a problem for me as well. A related problem for me is listing all such definitions in an object. I think addressing the two issues would make it possible to implement Enumeration without reflection, for example.
value x,y = Value
value z = Value(3)
translates to
val x = Value("x")
val y = Value("y")
val z = Value("z",3)
def values = Seq(x,y,z)
One could go further and write the above as:
value x,y,z(3)
-Mark
Note that in Scala (or other functional languages), the information might not be totally
accurate, as you can have lot of references to a method, allowing to call it with
alternative names...
def someMethod(n: Int): Int = { ... }
val otherMethod: Int => Int = someMethod
println(someMethod(11))
println(otherMethod(42))
In the stack traces, we see twice someMethod.
Or perhaps I am mixing methods and functions, the frontier is still blurry in my mind...
--
Philippe Lhoste
-- (near) Paris -- France
-- http://Phi.Lho.free.fr
-- -- -- -- -- -- -- -- -- -- -- -- -- --
No, those aren't methods.
> def someMethod(n: Int): Int = { ... }
> val otherMethod: Int => Int = someMethod
"otherFunction".
E.g. how to split an entry from the stack trace into correct parts?
Actually I do it with the extractor
val MethodNameParts = """([\w$]*\.)+([^\(]+)(.*)""".r
used as: val MethodNameParts(path, name, rest) = methodName
Can I rely on the schema of this construction?
How should the parts be named more correctly?
E.g. is it a correct spliting or am I missing something:
entry: test$1line15$object$$iw$$iw$.(<console>:7)
parts: name: test$1
path: line15$object$$iw$$iw$.
rest: (<console>:7)
?
I have a ton of code for this sort of thing, some of which is in trunk,
most of which isn't. Shoot, I had really meant to finish this for 2.9.
It basically works and is terribly useful, I just haven't put the
polish on the apple.
I put the branch in its current state on github. Look around the files
in this directory:
https://github.com/scala/scala/tree/funnel/src/compiler/scala/tools/funnel/
In terms of what's in trunk already, see Exceptional for a much reduced
preview of the above.
https://github.com/scala/scala/blob/master/src/compiler/scala/tools/nsc/util/Exceptional.scala
Correction: the "entry" in the prev. post should be:
line15$object$$iw$$iw$.test$1(<console>:7)
val MethodNameParts = """((?:[\w$]*\.)+)([^\(]+)(.*)""".r
On 2011-03-14 16:49, Paul Phillips wrote:
import java.lang.management._
def getCallingFunctionName(depth: Int): String = {
val mxBean = ManagementFactory.getThreadMXBean
val threadInfo =mxBean.getThreadInfo(Thread.currentThread.getId,depth)
val elements = threadInfo.getStackTrace
elements(depth-1).getMethodName
}
--
Quis custodiet ipsos custodes
I will try it.
Don't know if this is faster, but I've done this in the past:
import java.lang.management._
def getCallingFunctionName(depth: Int): String = {
val mxBean = ManagementFactory.getThreadMXBean
val threadInfo =mxBean.getThreadInfo(Thread.currentThread.getId,depth)
val elements = threadInfo.getStackTrace
elements(depth-1).getMethodName
}
I also then cache the method name based upon the method
body (() => R) and look up the name from the cache on
subsequent calls.
--
Quis custodiet ipsos custodes
This approach limits the size of the stack trace requested.
I would like to get the name of the current method programmatically (from within this method).
Is there eventually a more effective solution for Scala?
this is a very good news! Looking forward to it.
--
Eugen
On 2011-03-15 17:23, Adriaan Moors wrote: