开发者

Quotation real usages

开发者 https://www.devze.com 2023-04-07 04:37 出处:网络
I faced with the \'quotation\' term and I\'m trying to figure out some real-life examples of usage of it. Ability of having AST for each code expression sounds awesome, but how to use it in real lif开

I faced with the 'quotation' term and I'm trying to figure out some real-life examples of usage of it. Ability of having AST for each code expression sounds awesome, but how to use it in real lif开发者_如何学Ce?

Does anyone know such example?


F# and Nemerle quotations are both used for metaprogramming, but the approaches are different: Nemerle uses metaprogramming at compilation time to extend the language, while F# uses them at run time.

Nemerle

In Nemerle, quotations are used within macros for taking apart pieces of code and generating new ones. Much of the language itself is implemented this way. For example, here is an example from the official library — the macro implementing the when conditional construct. Nemerle does not have statements, so an if has to have an else part: when and unless macros provide shorthand for an if with an empty then and else parts, respectively. The when macro also has extended pattern-matching functionality.

macro whenmacro (cond, body)
syntax ("when", "(", cond, ")", body)
{
    match (cond)
    {
    | <[ $subCond is $pattern ]> with guard = null
    | <[ $subCond is $pattern when $guard ]> =>
        match (pattern)
        {
        | PT.PExpr.Call when guard != null =>
            // generate expression to replace 'when (expr is call when guard) body'
            <[ match ($subCond) { | $pattern when $guard => $body : void | _ => () } ]>
        | PT.PExpr.Call =>
            // generate expression to replace 'when (expr is call) body'
            <[ match ($subCond) { | $pattern => $body : void | _ => () } ]>
        | _ =>
            // generate expression to replace 'when (expr is pattern) body'
            <[ match ($cond) { | true => $body : void | _ => () } ]>
        }
    | _ =>
            // generate expression to replace 'when (cond) body'
            <[ match ($cond : bool) { | true => $body : void | _ => () } ]>
    }
}

The code uses quotation to handle patterns that look like some predefined templates and replace them with corresponding match expressions. For example, matching the cond expression given to the macro with:

<[ $subCond is $pattern when $guard ]>

checks whether it follows the x is y when z pattern and gives us the expressions composing it. If the match succeeds, we can generate a new expression from the parts we got using:

<[
    match ($subCond)
    {
    | $pattern when $guard => $body : void
    | _ => ()
    }
]>

This converts when (x is y when z) body to a basic pattern-matching expression. All of this is automatically type-safe and produces reasonable compilation errors when used incorrectly. So, as you see quotation provides a very convenient and type-safe way of manipulating code.


Well, anytime you want to manipulate code programmatically, or do some metaprogramming, quotations make it more declarative, which is a good thing.

I've written two posts about how this makes life easier in Nemerle: here and here.

For real life examples, it's interesting to note that Nemerle itself defines many common statements as macros (where quotations are used). Some examples include: if, for, foreach, while, break, continue and using.


I think quotations have quite different uses in F# and Nemerle. In F#, you don't use quotations to extend the F# language itself, but you use them to take an AST (data representation of code) of some program written in standard F#.

In F#, this is done either by wrapping a piece of code in <@ ..F# code.. @>, or by adding a special attribtue to a function:

[<ReflectedDefinition>]
let foo () = 
  // body of a function (standard F# code)

Robert already mentioned some uses of this mechanism - you can take the code and translate F# to SQL to query database, but there are several other uses. You can for example:

  • translate F# code to run on GPU
  • translate F# code to JavaScript using WebSharper


As Jordão has mentioned already quotations enable meta programming. One real world example of this is the ability to use quotations to translated F# into another language, like for example SQL. In this way Quotations server much the same purpose as expression trees do in C#: they enable linq queries to be translated into SQL (or other data-acess language) and executed against a data store.


Unquote is a real-life example of quotation usage.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号