¿Cómo creo un árbol de expresiones Linq con un F # lambda?

c# expression-trees f# linq

Pregunta

Esto es lo que se puede hacer en C # -

var two = 2;
System.Linq.Expressions.Expression<System.Func<int, int>> expr = x => x * two;
expr.Compile().Invoke(4); // returns 8

Deseo hacer el equivalente preciso en F #. Esto es lo que intenté, pero no compilé -

let two = 2
let expr = (fun x -> x * two) : System.Linq.Expressions.Expression<System.Func<int, int>>
expr.Compile().Invoke(4) // desired to return 8

Tal vez de manera predecible, la compilación falla en la línea 2 con el siguiente error:

"This function takes too many arguments, or is used in a context where a function is not expected."
let expr = (fun x -> x * two) : System.Linq.Expressions.Expression<System.Func<int, int>>
            ^^^^^^^^^^^^^^^^

Respuesta aceptada

No estoy seguro de por qué quiere evitar el uso de las citas F #: debajo de la cubierta, son casi lo mismo que los árboles de expresiones C # y si desea crear un árbol de expresiones en F #, el compilador utilizará las citas debajo de la cubierta En todo caso...

De todos modos, puede hacer esto sin escribir explícitamente <@ .. @> porque el compilador puede citar automáticamente una función cuando se pasa como un argumento a un método. Así que puedes hacer:

type Expr = 
  static member Quote(e:Expression<System.Func<int, int>>) = e

let two = 2
let expr = Expr.Quote(fun x -> x * two) 
expr.Compile().Invoke(4) // desired to return 8

EDITAR: Sin embargo, esto realmente compila a una cita de F # envuelta en una llamada que lo convierte en el árbol de expresiones de C #. Entonces, al final, obtendrás lo mismo que si escribieras:

open Microsoft.FSharp.Linq.RuntimeHelpers

let two = 2
let expr = 
  <@ System.Func<_, _>(fun x -> x * two) @>
  |> LeafExpressionConverter.QuotationToExpression 
  |> unbox<Expression<Func<int, int>>>
expr.Compile().Invoke(4) // desired to return 8


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow