引用真实用法

本文关键字:用法 真实 引用 | 更新日期: 2023-09-27 18:09:40

我遇到了"quotation"这个词,我想找出它在现实生活中的一些用法。为每个代码表达式提供AST的能力听起来很棒,但是在现实生活中如何使用它呢?

有人知道这样的例子吗?

引用真实用法

f#和Nemerle的引号都用于元编程,但方法不同:Nemerle在编译时使用元编程来扩展语言,而f#在运行时使用它们。

Nemerle

在Nemerle中,引号在宏中用于拆分代码片段并生成新代码。语言本身的大部分都是这样实现的。例如,这里有一个来自官方库的例子——实现when条件构造的宏。Nemerle没有语句,所以if必须有else部分:whenunless宏分别为if提供了一个空thenelse部分的简写。when宏还具有扩展的模式匹配功能。

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 | _ => () } ]>
    }
}

代码使用引号来处理看起来像一些预定义模板的模式,并用相应的match表达式替换它们。例如,用:

匹配给定给宏的cond表达式
<[ $subCond is $pattern when $guard ]>

检查它是否遵循x is y when z模式,并给出组成它的表达式。如果匹配成功,可以从使用

获得的部分生成一个新的表达式:
<[
    match ($subCond)
    {
    | $pattern when $guard => $body : void
    | _ => ()
    }
]>

这将when (x is y when z) body转换为基本的模式匹配表达式。所有这些都是自动类型安全的,并且在使用不当时产生合理的编译错误。因此,正如您所看到的,quote提供了一种非常方便且类型安全的操作代码的方式。

嗯,任何时候你想以编程方式操作代码,或者做一些元编程,引号使它更具有声明性,这是一件好事

我已经写了两篇关于这如何使Nemerle的生活更轻松的文章:在这里和在这里。

对于实际示例,有趣的是,Nemerle本身将许多常见语句定义为宏(其中使用引号)。例如:ifforforeachwhilebreakcontinueusing

我认为引用在f#和Nemerle中有完全不同的用途。在f#中,您不使用引号来扩展f#语言本身,而是使用它们来获取用标准f#编写的某些程序的AST(代码的数据表示)。

在f#中,这可以通过在<@ ..F# code.. @>中包装一段代码来完成,或者通过向函数添加一个特殊的属性来完成:

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

Robert已经提到了这种机制的一些用途——你可以用代码把f#转换成SQL来查询数据库,但是还有其他一些用途。例如:

  • 翻译f#代码在GPU上运行
  • 使用WebSharper将f#代码翻译成JavaScript

正如jord已经提到的,引号支持元编程。这方面的一个现实例子是使用引号将f#翻译成另一种语言的能力,例如SQL。通过这种方式,quotes服务的目的与c#中的表达式树非常相似:它们使linq查询能够被翻译成SQL(或其他数据访问语言),并在数据存储上执行。

Unquote是引号用法的一个现实例子。