funciones anonimas function f# parameters quotations

function - funciones anonimas matlab



¿Cómo obtener un nombre de una variable que entra en una función como parámetro usando F#? (3)

¿Hay alguna forma en F # de cómo obtener un nombre de una variable pasada a una función?

Ejemplo:

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

Gracias de antemano

EDITAR:

¿Por qué este código no funciona? Se compara como valor, por lo que no puedo recuperar el nombre de "variable".

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


En base a las soluciones anteriores, obtuve una solución más genérica donde puede obtener el nombre de funciones, lambdas, valores, propiedades, métodos, métodos estáticos, campos públicos, tipos de unión:

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


Es posible que pueda lograr esto con citas de código:

let name = fn <@ velocity @>

La función fn pasará un objeto Expr , que debe convertir a Quotations.Var (que solo será si pasa una única variable) y extraerá el miembro de instancia de Name .


Para completar la respuesta de Marcelo, sí, puedes usar citas para esta tarea:

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

Como puede ver en el código, los valores de definición superior de F # let-bound (funciones o variables) se implementan como propiedades de una clase.

No puedo encontrar más el enlace que muestra cómo una parte del código F # podría reescribirse de una manera funcional con C #. Al ver el código, resulta obvio por qué necesita un patrón PropertyGet .

Ahora, si también desea evaluar la expresión, necesitará instalar F # powerpack y hacer referencia a FSharp.PowerPack.Linq en su proyecto.

Agrega un método Expr clase Expr ..

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

Si necesita hacerlo por el método de una instancia, así es como lo haría:

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

Solo para volver al fragmento de código que muestra el uso de EvalUntyped , puede agregar un parámetro de tipo explícito para Expr y un Expr ( :?> ) Si desea / necesita mantener los tipos seguros.

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