jeremyh
jeremyh

Reputation: 644

Extract function name from a function

How can I create a function called getFuncName that takes a function of type (unit -> 'a) and returns its name.

I was talking to one of the C# devs and they said you could use the .Method property on a Func type as shown in an example here.

I tried to convert this to F# :

for example convert (unit -> 'a) to a type Func<_> then call the property on it but it always returns the string "Invoke".

let getFuncName f =
    let fFunc = System.Func<_>(fun _ -> f())
    fFunc.Method.Name

let customFunc() = 1.0

// Returns "Invoke" but I want it to return "customFunc"
getFuncName customFunc

A bit of background to this problem is:

I have created an array of functions of type (unit -> Deedle.Frame). I now want to cycle through those functions invoking them and saving them to csv with the csv name having the same name as the function. Some hypothetical code is below:

let generators : (unit -> Frame<int, string>) array = ...

generators
|> Array.iter (fun generator -> generator().SaveCsv(sprintf "%s\%s.csv" __SOURCE_DIRECTORY__ (getFuncName generator)))

This is being used in a scripting sense rather than as application code.

Upvotes: 3

Views: 684

Answers (1)

FoggyFinder
FoggyFinder

Reputation: 2220

Not sure how you searched for information, but the first query to the search engine gave me this response:

let getFuncName f =
   let type' = f.GetType()
   let method' = type'.GetMethods() |> Array.find (fun m -> m.Name="Invoke")

   let il = method'.GetMethodBody().GetILAsByteArray()
   let methodCodes = [byte OpCodes.Call.Value;byte OpCodes.Callvirt.Value]

   let position = il |> Array.findIndex(fun x -> methodCodes |> List.exists ((=)x))
   let metadataToken = BitConverter.ToInt32(il, position+1) 

   let actualMethod = type'.Module.ResolveMethod metadataToken
   actualMethod.Name

Unfortunately, this code only works when F# compiler does not inline function body into calling method.

Taken from here

Although there may be a more simple way.

Upvotes: 1

Related Questions