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.

1 Answer 1

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 @>
Sign up to request clarification or add additional context in comments.

5 Comments

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.
So for qwrap dummy I would like to have val it : Expr<(int -> string)> = Lambda (x, Call (None, dummy, [x]))
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.
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...
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...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.