我面对'引用'这个术语,我试图弄清楚一些现实生活中使用它的例子。为每个代码表达式设置AST的能力听起来很棒,但是如何在现实生活中使用它?
有谁知道这样的例子?
答案 0 :(得分:5)
F#和Nemerle引用都用于元编程,但方法不同:Nemerle在编译时使用元编程来扩展语言,而F#在运行时使用它们。
在Nemerle中,引用在宏中用于分离代码片段并生成新代码。大多数语言本身都是以这种方式实现的。例如,这是官方库中的一个示例 - 实现when
条件构造的宏。 Nemerle没有声明,因此if
必须有else
部分:when
和unless
宏为空if
提供简写then
分别为1}}和else
部分。 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
转换为基本模式匹配表达式。所有这些都是自动类型安全的,并且在错误使用时会产生合理的编译错误。因此,正如您所看到的,引用提供了一种非常方便且类型安全的操作代码的方式。
答案 1 :(得分:4)
好吧,无论何时你想以编程方式操作代码,或者做一些元编程,引用都会使它更加声明,这是一件好事。
我写过两篇关于如何让Nemerle生活更轻松的帖子:here和here。
对于现实生活中的例子,有趣的是,Nemerle本身将许多常见语句定义为宏(使用引号)。一些示例包括:if
,for
,foreach
,while
,break
,continue
和using
。
答案 2 :(得分:2)
我认为引用在F#和Nemerle中有很多不同的用法。在F#中,您不使用引号来扩展F#语言本身,而是使用它们来获取用标准F#编写的某些程序的AST(代码的数据表示)。
在F#中,这可以通过在<@ ..F# code.. @>
中包装一段代码,或者通过向函数添加特殊的属性来完成:
[<ReflectedDefinition>]
let foo () =
// body of a function (standard F# code)
Robert已经提到了这种机制的一些用法 - 你可以使用代码并将F#翻译为SQL to query database,但还有其他一些用途。例如:
答案 3 :(得分:1)
正如Jordão已经提到的,引用已启用元编程。一个真实世界的例子就是能够使用引号将F#翻译成另一种语言,例如SQL。通过这种方式,Quotations服务器与表达式树在C#中的作用大致相同:它们使linq查询能够转换为SQL(或其他数据访问语言)并针对数据存储执行。
答案 4 :(得分:1)
Unquote是引用用法的真实示例。