Hi Mat, I'm not that familiar with the Quotations API yet, but all of the information seems like it is available. Running FSI in the Visual Studio 10 beta, here is what I see:

Microsoft F# Interactive, (c) Microsoft Corporation, All Rights Reserved
F# Version 1.9.6.16, compiling for .NET Framework Version v4.0.20506

> let f x (y,z) = x + y + z;;

val f : int -> int * int -> int

> let fqe = <@ f @>;;

val fqe : Quotations.Expr<(int -> int * int -> int)> =
Lambda (x,
Lambda (tupledArg,
Let (y, TupleGet (tupledArg, 0),
Let (z, TupleGet (tupledArg, 1),
Call (None, Int32 f(Int32, Int32, Int32), [x, y, z])))))

fqe.Type
Microsoft.FSharp.Core.FastFunc`2[System.Int32,Microsoft.FSharp.Core.FastFunc`2[System.Tuple`2[System.Int32,System.Int32],System.Int32]]

It looks like you should be able to figure out what your looking for and print out something like:
x: Int32
yz: Tuple`2<Int32,Int32>

I started looking at it a couple of weekends ago, but ran out of time. I am still trying to figure out if there is a way to do code generation with Quotations, or should I resort to a template system like NDjango?

By on 6/3/2009 11:12 PM ()

If you have the reflected definition of a function, then you can probably put together something based on the quotation output like you say, but this would be quite fragile and could quite well break with each release of the compiler.

For functions without reflected definitions, you're in worse shape: for example, how can you tell that the function LanguagePrimitives.GenericZero<T> does not take an empty tuple as an argument, while Lazy<T>.force() does? Given the MethodInfo of the compiled method leaves you none the wiser....

By on 6/8/2009 2:49 PM ()

In the next release (Beta2), it is likely that F# will add an attribute (e.g. CompilationArgumentCountsAttribute) that reflects the "F# arity" of compiled methods, so that you can tell via reflection e.g. the F# structural difference between

type Foo() =

member this.Tupled(x,y) = x + y

member this.Curried x y = x + y

even if they have the same shape in IL.

By on 6/8/2009 3:06 PM ()

'f' is compiled into a static method taking three ints, as described in 8.3.4 of the language spec:

[link:research.microsoft.com]

(and you can see this by e.g. using .Net Reflector on the generated assembly).

In short, the .Net compiled form does not always match the "F# type", as F# uses extra F#-specific metadata to represent such functions. Since you're getting a MethodInfo, you see it the .Net way.

By on 3/17/2009 4:24 PM ()

This is one of the things in F# reflection that has bitten me too. Is there a library function that is able to convert between the compiled and the actual form? 

By on 3/18/2009 12:49 AM ()

Thanks Brian (spooky that I chose the same example as the language spec...)

Unless there is a library function like Kurt describes above, the loss of information that occurs by having "MethodInfo" as the second result of (|Call|_|) makes it impossible to do a source code transformation (F# code with reflected definition -> F# code).

It seems like (|Call|_|) should instead return a "FSharpMethodInfo" type which preserves the F# specific meta-information that you mention, part of which should include the MethodInfo compiled representation information....

By on 3/18/2009 5:13 AM ()

Alternately, perhaps the MethodInfo could be decorated with a custom attribute containing sufficient information such that an alternate version of (|Call|_|) returned an Expr list list for the arguments instead of the flattened Expr list?

By on 3/18/2009 4:01 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper