Para completar la respuesta de Marcelo, sí se puede utilizar 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 <@[email protected]>
printfn "%s" name
Como se puede ver en el código, F # let-atado valores de definición superior (funciones o variables) se implementan como propiedades de una clase.
No encuentro más el enlace que muestra cómo una parte del código F # podría reescribirse de forma funcional con C#. Al ver el código, resulta obvio por qué necesita un patrón PropertyGet
.
Ahora, si quiere evaluar la expresión también, necesitará instalar F# powerpack y hacer referencia FSharp.PowerPack.Linq
en su proyecto.
Se añade un método EvalUntyped
en Expr
clase ..
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 <@[email protected]>
printfn "%s %A" name value
Si tiene que 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 <@[email protected]>
printfn "%s" name
let foo = new Foo()
let methodName = fn <@[email protected]>
printfn "%s" methodName
Sólo para vuelva al fragmento de código que muestra el uso de EvalUntyped
, puede agregar un parámetro de tipo explícito para Expr
y un downcast (:?>
) si desea/necesita mantener las cosas seguras:
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 <@[email protected]> //value has type int here
printfn "%s %d" name value
Hola, gracias mucho! Una pregunta adicional. ¿Cómo obtengo un valor de la expresión? –
Gracias! Y una pregunta final :) Si el fn es miembro de un tipo (member this.fn = ...), ¿cómo lo hago? –
Para ser curioso, ¿por qué necesita recuperar el nombre de un valor/miembro? – Stringer