【问题标题】:How to get the name of function argument in F#?如何在 F# 中获取函数参数的名称?
【发布时间】:2015-06-18 10:00:33
【问题描述】:

我可以编写一个函数,返回作为参数给出的函数的名称吗?

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 之类的内容检索函数的摘要,我想知道函数的名称。

【问题讨论】:

  • 你到底想在这里实现什么 - 在 F# 中使用 currying 这可能很复杂。
  • 可能类似于CallerMemberNameAttribute? OP 可能已经看到了这一点,但我会作为注释添加(参见 Nikon the Third 评论)。

标签: reflection f#


【解决方案1】:

我无法想象你为什么要这样做,而且我认为没有办法通过反射来做到这一点,但F# Code Quotations 可能会让你成功。

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"

【讨论】:

  • 我经常遇到的一个用例是在实现INotifyPropertyChanged 时使用类似的东西。我绝对鄙视必须返回字符串。
  • 另一个用例是代码生成。例如,今天我想创建一个 Rust 静态数组,我已经在我的 F# 代码中拥有它。数组中的结构包含函数指针。我没有用 Rust 语法再次输入整个表,而是编写了一个脚本,但必须找到结构中引用的函数的名称。不要质疑人们的用例;)
【解决方案2】:

请注意,从 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 2023-03-27
    • 2018-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多