How to get the name of a variable entering a function as a parameter using F #?

Is there a way in F # how to get the name of a variable passed to a function?

Example:

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

Thank you in advance

EDIT:

Why is this code not working? It maps to a value, so I cannot get the variable name.

 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 
+6
function parameters f # quotations
source share
3 answers

To complete Marcelo's answer yes, you can use quotes for this task:

 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 

As you can see in the code, F # let-bound values โ€‹โ€‹of the upper definition (functions or variables) are implemented as properties of the class.

I can no longer find a link that shows how part of the F # code can be rewritten functionally using C #. Seeing the code makes it obvious why you need a PropertyGet .

Now, if you also want to evaluate the expression, you will need to install F # powerpack and the FSharp.PowerPack.Linq link in your project.

It adds the EvalUntyped method to the EvalUntyped 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 

If you need to do this for an instance method, here is how I would do it:

 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 

To return to the code snippet showing the use of EvalUntyped , you can add an explicit type parameter for Expr and downcast ( :?> ) If you want / should store things in a type:

 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 
+11
source share

You may be able to achieve this with code suggestions:

 let name = fn <@ velocity @> 

The fn function will be passed to the Expr object, which it should pass to Quotations.Var (which will only happen if you pass one variable) and extract the instance element Name .

+1
source share

Based on previous solutions, I came up with a more general solution, in which you can get the name of functions, lambda, values, properties, methods, static methods, open fields, Union types:

 open Microsoft.FSharp.Quotations open Microsoft.FSharp.Quotations.Patterns let cout (s:string)= System.Console.WriteLine (s) let rec getName exprs = let fixDeclaringType (dt:string) = match dt with | fsi when fsi.StartsWith("FSI_") -> "Fsi" | _ -> dt let toStr (xDeclType: System.Type) x = sprintf "%s.%s" (fixDeclaringType xDeclType.Name) x match exprs with | Patterns.Call(_, mi, _) -> toStr mi.DeclaringType mi.Name | Patterns.Lambda(_, expr) -> getName expr | Patterns.PropertyGet (e, pi, li) -> toStr pi.DeclaringType pi.Name | Patterns.FieldGet (_, fi) -> toStr fi.DeclaringType fi.Name | Patterns.NewUnionCase(uci, _) -> toStr uci.DeclaringType uci.Name | expresion -> "unknown_name" let value = "" let funcky a = a let lambdy = fun(x) -> x*2 type WithStatic = | A | B with static member StaticMethod a = a let someIP = System.Net.IPAddress.Parse("10.132.0.48") getName <@ value @> |> cout getName <@ funcky @> |> cout getName <@ lambdy @> |> cout getName <@ WithStatic.A @> |> cout getName <@ WithStatic.StaticMethod @> |> cout getName <@ someIP.MapToIPv4 @> |> cout getName <@ System.Net.IPAddress.Parse @> |> cout getName <@ System.Net.IPAddress.Broadcast @> |> cout 
0
source share

All Articles