如何在F#中打印调用函数时传入的实参函数名称?
解决F#中打印传入函数的实参名称问题
核心思路
nameof是编译时操作符,只能获取当前作用域内的符号名称(比如形参f)。要拿到传入的实参函数名,需要借助F#的**代码引用(Quotations)**功能——它能捕获代码的结构信息,包括原函数的名称标识。
修改后的实现代码
open System open System.Threading.Tasks open Microsoft.FSharp.Quotations open Microsoft.FSharp.Quotations.Patterns // 辅助函数:从代码引用中解析函数名称 let getFunctionName (expr: Expr<'a -> Task<'b>>) = match expr with | Lambda (_, Call (_, methodInfo, _)) -> methodInfo.Name | Lambda (_, PropertyGet (_, propInfo, _)) -> propInfo.Name | _ -> failwith "无法识别的函数形式" // 改造后的logger函数,接收函数的代码引用 let logger (expr: Expr<'a -> Task<'b>>) : ('a -> Task<'b>) = let funcName = getFunctionName expr printfn "Hey: %s" funcName // 将引用编译为可执行函数 expr.Evaluate() let myFunc x = task { return x } // 调用时用<@ ... @>包裹函数,传入代码引用 let d = (logger <@ myFunc @>) 3
代码说明
- 引用包裹:调用
logger时,用<@ myFunc @>将目标函数包装成代码引用,保留myFunc的名称元信息。 - 解析名称:
getFunctionName通过匹配引用的模式(如Lambda、PropertyGet),提取出原函数的名称字符串。 - 编译执行:
expr.Evaluate()将代码引用转换成可执行的函数,保证原函数的业务逻辑不受影响。
注意事项
- 若传入匿名函数,这种方法无法获取有效名称,可根据需求扩展错误处理逻辑。
- 项目需确保引用
Microsoft.FSharp.Linq包(.NET Core/.NET 5+项目通常已默认包含)。
内容的提问来源于stack exchange,提问作者Tuomas Hietanen
相关产品推荐
相关产品推荐

