On the F# List Roshan James recently asked some good questions about F# quotations. I thought I'd record them here along with my answers.
-----------
Hi Roshan,
Can I evaluate a <@@ 1 + 2 @@> term to value?
The primary rationale for quotations is to allow fragments of F# syntax to be executed "by alternative means", e.g. as an SQL query via LINQ or by running on a GPU. This is the same rationale as C# LINQ Expression trees. We want to leverage heavy-hitting components that map subsets of functional programs to other execution machinery. Another example might be executing a subset of F# array code by dynamic generation of Fortran code, invocation of a vectorizing Fortran compiler and loading and invoking the resulting DLL dynamically.
The FLinq sample is the primary example of this. From academic point you might call this "offshoring staged computation". This is discussed in my paper at
http://research.microsoft.com/~dsyme/papers/ml03-syme.pdf
As an example, we have recently been re-working the SQL portion of the F# FLinq sample. This builds on top of the reworked quotations API in the 1.9.1 release (http://blogs.msdn.com/dsyme/archive/2007/04/06/f-1-9-1-released.aspx.) It now uses a combination of F# Quotations and LINQ to implement what a dynamic evaluator for Expr<’a> expressions:
val SQL : Expr<'a> -> 'a
You can then execute a subset of Expr<’a> values as database queries – some examples are shown below. We’ll release this new sample in the next couple of weeks, and you can also play around with the current FLinq sample that does things a bit differently.
SQL <@ { for c in (§db.Customers)
when c.City = "London"
-> c } @>
SQL <@ { for e in (§db.Employees)
-> e.FirstName + " " + e.LastName, e.HomePhone } @>
SQL <@ { for c in (§db.Customers)
-> (c.CustomerID,
(c.CompanyName, c.City, c.Country),
(c.ContactName, c.ContactTitle)) } @>
SQL <@ { for e in (§db.Employees)
for et in e.EmployeeTerritories
when e.City = "Seattle"
-> (e.FirstName, e.LastName, et.Territory.TerritoryDescription) } @>
All of this means we're not (yet) particularly interested in executing quotations as F# code on the CPU of the local machine. This is initially counter-intuitive to those steeped in Lisp, Scheme or staged computation, but usually the SQL sample helps people see the point.
You can compile/interpret on the CPU if you are willing to write your own interpreter or dynamic compiler for the expression trees, or translate expression fragments to LINQ and use their (somewhat limited) dynamic compiler. This is also covered briefly in the paper above.
I'm also pretty certain we will eventually support using the F# compiler to “eval” quotations, but we don’t do that yet.
Can I effectively ToString a quotation?
Printing is considerably better supported in the 1.9.1 release, though is not perfect. You may need to write your own pretty printer.
Can I introduce new syntax using a <@@ @@> term somehow?
No, this is not what quotations are for.
Finally, is the diffrence between <@ .. @> and <@@ ... @@> only
that the former is not run
Type inference applies to both. The only difference between the two is that the type from the surrounding context is not propagated through the type checking of the <@@ @@> expression.
Don