Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically figuring out function name in f#

If I have a function that is part of a module, and I want a log entry while inside the function,I have to manually print the function namespace and name e.g.

namespace MyModuleNamespace
 module MyModule = 
 let AddTwoNums logger x y =
    logger.Info("MyModuleNamespace.AddTwoNums - Start")
    let res = x+y
    logger.Info("MyModuleNamespace.AddTwoNums - End")
    res

Is there any way I can automatically work out what "MyModuleNamespace.AddTwoNums" is as it is very cumbersome/error prone especially when you have to rename functions and modules during refactoring of code

Even if that cannot be done, is there any way I can automatically work out what "AddTwoNums" is i.e. the function name?

like image 471
bstack Avatar asked Sep 28 '18 11:09

bstack


People also ask

How do you get a function name inside a function in Python?

Method 1: Get Function Name in Python using function. func_name.

Can you use a string to call a function?

There are two methods to call a function from string stored in a variable. The first one is by using the window object method and the second one is by using eval() method.

How do you name a function in JavaScript?

A JavaScript function is defined with the function keyword, followed by a name, followed by parentheses (). Function names can contain letters, digits, underscores, and dollar signs (same rules as variables). The parentheses may include parameter names separated by commas: (parameter1, parameter2, ...)

How do you call a function by its string name in Python?

String To Function Using The eval() Function In Python We can also use the eval() function to convert a string to a function. Here, the input string is the name of the function. In the eval() function, we will pass the name of the function and the ' () ' separated by the addition symbol ' + '.


2 Answers

There are a couple ways to do this, and I'm not sure which would be the best one for your scenario. One way that I've used in the past is to get the information from the stack trace:

let stackTrace = StackTrace()
let topFrame = stackTrace.GetFrame(0)
let currentFunction = topFrame.GetMethod()
printfn "%s.%s" currentFunction.DeclaringType.Name currentFunction.Name

In order to keep from having to put these lines in every function, you can make an inline function that does this, which will give you the name of the calling function due to the inlining.

let inline getCurrentFunction () =
    let stackTrace = StackTrace()
    let topFrame = stackTrace.GetFrame(0)
    let currentFunction = topFrame.GetMethod()
    sprintf "%s.%s" currentFunction.DeclaringType.Name currentFunction.Name
like image 104
Aaron M. Eshbach Avatar answered Oct 01 '22 12:10

Aaron M. Eshbach


If you don't need the actual namespace / module name or are willing to replace that with the file name, there are special attributes that instruct the compiler to supply corresponding arguments to a function:

open System.Runtime.CompilerServices

type Logger =
    static member Trace(
                        msg: string,
                        [<CallerMemberName>] ?memberName: string,
                        [<CallerFilePath>] ?path: string,
                        [<CallerLineNumberAttribute>] ?line: int) =
        printfn "%s from %s.%s on line %i" msg path.Value memberName.Value line.Value

module Foo =
    let bar() =
        Logger.Trace("hello")

// hello from c:\path\to\Logging.fsx.bar on line 32
Foo.bar()

MS Docs has more to say about Caller Information.

Note that when your run this from within fsi, the line number is only accurate the first time.

like image 25
CaringDev Avatar answered Oct 01 '22 14:10

CaringDev