Reputation: 81536
I hope I haven't missed something obvious, but I've been playing with F# expressions and I want to evaluate quoted expressions on the fly. For example, I want write something like this:
let x = <@ 2 * 5 @>
let y = transform x // replaces op_Multiply with op_Addition, or <@ 2 + 5 @>
let z = eval y // dynamically evaluates y, returns 7
Is there a built-in F# method which can evaluate quoted expressions, or do I have to write my own?
Upvotes: 13
Views: 3527
Reputation: 3804
Updated in 2016
The Evaluate
extension method can now be found in NuGet package FSharp.Quotations.Evaluator
#r "../packages/FSharp.Quotations.Evaluator.1.0.7/lib/net40/FSharp.Quotations.Evaluator.dll"
open FSharp.Quotations.Evaluator
let f = <@ 2 + 3 @>
f.Evaluate()
Upvotes: 7
Reputation: 22307
I've implemented a reflection-based Quotation evaluator as part of Unquote (this is a new feature as of version 2.0.0).
> #r @"..\packages\Unquote.2.2.2\lib\net40\Unquote.dll"
--> Referenced '..\packages\Unquote.2.2.2\lib\net40\Unquote.dll'
> Swensen.Unquote.Operators.eval <@ sprintf "%A" (1,2) @>;;
val it : string = "(1, 2)"
I've measured it to be up to 50 times faster than PowerPack's evaluator. This will, of course, vary by scenario. But Unquote is generally magnitudes faster than PowerPack at interpreting expressions.
It also supports many more expressions than PowerPack's evaluator, including VarSet, PropertySet, FieldSet, WhileLoop, ForIntegerRangeLoop, and Quote. In fact, Unquote's evaluator supports all quotation expressions except NewDelegate, AddressSet, and AddressOf all of which I plan on eventually supporting.
Upvotes: 18
Reputation: 48707
You can evaluate an F# quotation using the Eval
extension member provided by the FSharp.PowerPack.Linq
DLL as follows:
#r "FSharp.PowerPack.Linq.dll"
open Linq.QuotationEvaluation
let f = <@2 + 3@>
f.Eval()
Note that you must open
the Linq.QuotationEvaluation
namespace to make this extension member available.
There is also a Compile
extension member that returns a suspension but it does not appear to improve performance.
Upvotes: 8
Reputation: 10006
No, there's no built-in way to compile F# quotations. With the PowerPack LINQ you can convert SOME quotations to .NET System.Linq.Expressions.Expression, and use that to compile them.
Quotations were made to allow other interpretations of code, such as targeting SQL or a GPU card.
However, in posts on hubfs, it's been hinted at that this is a common request and will be looked at.
Upvotes: 9