function - 如何使用 F# 获取作为参数进入函数的变量的名称?

标签 function f# parameters quotations

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

例子:

let velocity = 5
let fn v = v.ParentName
let name = fn velocity // this would return "velocity" as a string

先感谢您

编辑:

为什么这段代码不起作用?它作为值匹配,因此我无法检索“变量”名称。
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

最佳答案

为了完成 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
正如您在代码中看到的那样,F# let-bound 顶部定义值(函数或变量)被实现为类的属性。
我再也找不到显示如何使用 C# 以功能方式重写一段 F# 代码的链接。看到代码,很明显为什么需要 PropertyGet图案。
现在如果你也想计算表达式,你需要安装 F# powerpack和引用 FSharp.PowerPack.Linq在你的项目中。
它添加了 EvalUntyped Expr上的方法类(class)..
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
如果您需要为实例的方法执行此操作,我将这样做:
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
只是回到显示 EvalUntyped 用法的代码片段。 ,您可以为 Expr 添加显式类型参数如果您想要/需要保持类型安全,请使用向下转换 ( :?> ):
let fn (e:Expr<'T>) = 
  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

关于function - 如何使用 F# 获取作为参数进入函数的变量的名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2736192/

相关文章:

F# 等于运算符复杂度

asp.net-web-api - 为什么我的 IExceptionHandler 实现没有返回错误响应?

java - 如何从 run 方法中获取值?

c# - 类型参数中具有层次结构的受限泛型

c++ - template<typename T> using L = T(*)(T); 中的 (*) 是什么意思?

javascript - 当行数未知时,使用 javascript 更改行的类

c++ - 如何保持存储在作为参数传递的指针中的地址在所有函数调用中保持一致

f# - 保护 WebSharper 远程调用

oracle - PLSQL - 创建带参数的过程,但只允许 2 个值

这段代码可以称为递归吗?如果不是,下面给出的代码或递归哪个更有优势?