如何在F#中获取函数参数的名称?

6
我可以编写一个函数,该函数返回给定参数的函数名称吗?
let funName f: string =
   // returns the name of f.

例如,如果我将printfn作为funName的参数传递,它会返回"printfn"。
> funName printfn;;
val it : string = "printfn"

编辑:我想编写一个函数doc,该函数返回与给定函数相关联的XML文档。

let doc f = // returns the XML documentation of the function `f`.

使用类似NuDoq的方式检索函数摘要,我想知道函数的名称。

2
你实际上在这里想要实现什么 - 在 F# 中使用柯里化可能会很复杂。 - John Palmer
也许类似于CallerMemberNameAttribute?楼主可能已经看到了,但我会作为一个注释添加上(参见Nikon the Third的评论)。 - Veksi
2个回答

10

我无法想象为什么你想这样做,而且我认为没有一种反射的方法可以做到这一点,但是F#代码引用或许可以让你达到一半的目标。

open Microsoft.FSharp.Quotations

let rec funName = function
| Patterns.Call(None, methodInfo, _) -> methodInfo.Name
| Patterns.Lambda(_, expr) -> funName expr
| _ -> failwith "Unexpected input"

let foo () = 42
funName <@ foo @>       // "foo"

但请注意,某些预定义的库函数具有不同的内部名称。

funName <@ printfn @>   // "PrintFormatLine"
funName <@ id @>        // "Identity"

2
我经常遇到的一个使用案例是在实现“INotifyPropertyChanged”时使用类似的东西。我非常讨厌不得不返回字符串。 - Nikon the Third
另一个用例是代码生成。例如,今天我想创建一个Rust静态数组,在我的F#代码中已经有了。数组内的结构包含函数指针。我不需要再用Rust语法重新输入整个表格,只需编写一个脚本就行,但必须找到结构中引用的函数的名称。不要质疑人们的用例 ;) - BitTickler

5
注意,从F# 4.0开始,类类型可以自动引用它们的参数,相较于kaefer的答案,简化了调用过程。
open Microsoft.FSharp.Quotations

type DocumentGetter =
    static member GetName([<ReflectedDefinition>]x:Expr<_->_>) = 
        match x with
        | DerivedPatterns.Lambdas(_, Patterns.Call(_,methodInfo,_)) ->
            methodInfo.Name

let f x y = x + y

DocumentGetter.GetName f

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接