0

Let's have the following function definition:

module Helpers =

    [<ReflectedDefinition>]
    let dummy (x:int) = x.ToString()

By using the following quotation we get its representation as a lambda expression:

<@ dummy @>;;

val it : Expr<(int -> string)> =
Lambda (x, Call (None, dummy, [x]))

In this previous question it is stated that quotations represent code quoted syntactically, that meaning that we can not get the same expression by wrapping the same function within other function:

let qwrap f = <@ f @>
qwrap dummy;;

val it : Expr<(int -> string)> =
Value (<fun:it@6-3>)

Is it possible to build the former expression (Lambda (x, Call (None, dummy, [x]))) programmatically?. The objective would be to implement a dynamic qwrap for simple functions ('a -> 'b). The resulting expression is going to be analyzed and I'm interested in being able to keep the function and args names as they are written in the original function.

Community
  • 1
  • 1
jruizaranguren
  • 12,679
  • 7
  • 55
  • 73

1 Answers1

2

Just to make sure I understand your question correctly, you would like to write some function that wraps a function (possibly represented as a quotation) and adds some other things around it?

The reason why your qwrap function returns Value is that <@ f @> simply creates a quotation that represents the value of f and embeds it as an object - it does not know what f is.

If you want to create a quotation that wraps another quotation, your argument f needs to be a quotation too. Then you can use <@ %f @> to create a new quotation which contains the original quotation (the % syntax is a splicing operator).

Here is a simple example that adds check for zero:

let qwrap f = 
  <@ fun x -> 
      if x = 0 then failwith "No!" 
      else (%f) x @>

You can call qwrap with any quoted function as an argument:

let dummy (x:int) = x.ToString()
qwrap <@ dummy @>
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • No, I want to write some function that takes a function "dummy" that it is not represented by a quotation (any function 'a -> 'b where 'a, 'b can be any type) and gets the same representation that quoting manually would do, ie <@ dummy @>. I was wondering if by doing it programmatically instead of quoting we could avoid the syntatic problem you mentioned in related question. – jruizaranguren Sep 11 '14 at 16:25
  • So for qwrap dummy I would like to have val it : Expr<(int -> string)> = Lambda (x, Call (None, dummy, [x])) – jruizaranguren Sep 11 '14 at 16:26
  • 1
    I think he wants to create something like `let qwrap (f:'a->'b) = let x = Var("x", typeof<'a>) in Expr.Lambda(x, Expr.Call(F, Expr.Var x))`but the problem is that F should be the methodinfo of f which is not straightforward to get in this scenario. – Gus Sep 12 '14 at 15:23
  • 2
    Oh, I see. Getting method info from a function value is not really possible (well, not *reasonably* possible). I'd suggest changing the design, so that it isn't needed... – Tomas Petricek Sep 14 '14 at 22:47
  • I will probably try to change the design, but I'm getting all needed features so far (except a convention validation which would make everything more robust). Perhaps I could try a different approach by writting some parts dynamically and compile them with Compiler.Services. No many docs or samples out there... – jruizaranguren Sep 15 '14 at 07:16