我遇到了“引用”这个词,我正在尝试找出一些现实生活中使用它的例子。为每个代码表达式使用AST的能力听起来很棒,但如何在现实生活中使用它呢?
有人知道这样的例子吗?
发布于 2011-09-23 14:14:33
我认为引用在F#和Nemerle中的用法是完全不同的。在F#中,不使用引号来扩展F#语言本身,而是使用它们来获取一些用标准F#编写的程序的AST (代码数据表示)。
在F#中,这可以通过在<@ ..F# code.. @>
中包装一段代码,或者通过向函数添加特殊属性来完成:
[<ReflectedDefinition>]
let foo () =
// body of a function (standard F# code)
罗伯特已经提到了这种机制的一些用途--您可以将代码转换为SQL to query database,但还有其他几种用途。例如,您可以:
发布于 2011-09-24 21:05:07
F#和Nemerle引用都用于元编程,但方法不同: Nemerle在编译时使用元编程来扩展语言,而F#在运行时使用它们。
内梅尔
在Nemerle中,在宏中使用引号来拆分代码并生成新的代码。语言本身的大部分都是以这种方式实现的。例如,下面是一个来自官方库的示例--实现when
条件构造的宏。Nemerle没有语句,所以if
必须有一个else
部分:when
和unless
宏分别为具有空then
和else
部分的if
提供了简写。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
转换为基本的模式匹配表达式。所有这些都是自动类型安全的,并且在使用不当时会产生合理的编译错误。因此,正如您所看到的,quotation提供了一种非常方便且类型安全的代码操作方法。
https://stackoverflow.com/questions/7529496
复制相似问题