如何使用F#获取作为参数的函数名称?

Old*_*vec 6 parameters f# function quotations

在F#中有什么方法可以获取传递给函数的变量的名称吗?

例:

let velocity = 5
let fn v = v.ParentName
let name = fn velocity // this would return "velocity" as a string
Run Code Online (Sandbox Code Playgroud)

先感谢您

编辑:

为什么这段代码不起作用?它匹配为值,因此我无法检索"变量"名称.

type Test() =
  let getName (e:Quotations.Expr) =
    match e with
      | Quotations.Patterns.PropertyGet (_, pi, _) -> pi.Name + " property"
      | Quotations.Patterns.Value(a) -> failwith "Value matched"
      | _ -> failwith "other matched"
  member x.plot v = v |> getName |> printfn "%s"

let o = new Test()

let display () =
  let variable = 5.
  o.plot <@ variable @>

let runTheCode fn = fn()

runTheCode display
Run Code Online (Sandbox Code Playgroud)

Str*_*ger 11

要完成Marcelo的回答,是的,您可以使用引用来完成此任务:

open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns

let velocity = 5

let fn (e:Expr) =
  match e with
    | PropertyGet (e, pi, li) -> pi.Name
    | _ -> failwith "not a let-bound value"

let name = fn <@velocity@> 

printfn "%s" name
Run Code Online (Sandbox Code Playgroud)

正如您在代码中看到的那样,F#let-bound顶级定义值(函数或变量)被实现为类的属性.

我找不到链接,它显示了如何用C#以功能方式重写一段F#代码.看到代码,很明显为什么你需要一个PropertyGet模式.

现在,如果您还要评估表达式,则需要在项目中安装F#powerpack和reference FSharp.PowerPack.Linq.

EvalUntypedExpr类上添加了一个方法..

open Microsoft.FSharp.Linq.QuotationEvaluation

let velocity = 5

let fn (e:Expr) =
  match e with
    | PropertyGet (eo, pi, li) -> pi.Name, e.EvalUntyped
    | _ -> failwith "not a let-bound value"

let name, value = fn <@velocity@> 

printfn "%s %A" name value
Run Code Online (Sandbox Code Playgroud)

如果您需要为实例的方法执行此操作,请按以下步骤操作:

let velocity = 5

type Foo () =
  member this.Bar (x:int) (y:single) = x * x + int y

let extractCallExprBody expr =
  let rec aux (l, uexpr) =
    match uexpr with
     | Lambda (var, body) -> aux (var::l, body)
     | _ -> uexpr
  aux ([], expr)

let rec fn (e:Expr) =
  match e with
    | PropertyGet (e, pi, li) -> pi.Name
    | Call (e, mi, li) -> mi.Name
    | x -> extractCallExprBody x |> fn
    | _ -> failwith "not a valid pattern"

let name = fn <@velocity@> 
printfn "%s" name

let foo = new Foo()

let methodName = fn <@foo.Bar@>
printfn "%s" methodName
Run Code Online (Sandbox Code Playgroud)

只是回到显示使用情况的代码片段EvalUntyped,如果您希望/需要保持类型安全,可以添加显式类型参数Expr和downcast(:?>):

let fn (e:Expr<´T>) = //using ´ instead of ' to avoid colorization screw-up
  match e with
    | PropertyGet (eo, pi, li) -> pi.Name, (e.EvalUntyped() :?> ´T)
    | _ -> failwith "not a let-bound value"

let name, value = fn <@velocity@> //value has type int here
printfn "%s %d" name value
Run Code Online (Sandbox Code Playgroud)