在拟抽样中“准”的含义是什么?
一些像Haskell(或Nemerle)这样的语言有quasiquotations 。 我不知道“准”是什么意思,如果没有“准”部分也存在“引用”。
我相信这个概念来自Lisp语言。
用Lisp编写的程序由一系列列表列表组成,如下所示:
(defn f [xy] (+ xy))
由于这种一致性,可以表示和处理这样的代码作为数据,所以上面的字符序列被解释为文字列表。 这是Lisps的一个非常有用的function,它们的特色之一。 为了方便,Lisp语言允许“引用”有意义的序列,将它们从定义和expression式转换为列表。 它看起来像这样:
'(defn f [xy] (+ xy))
在这种情况下,它是一个文字列表,直接可用于使用Haskell的head
和tail
类似物解构和其他方法。 所以,'quote'的意思是“从列表中创造一个文字值”。
但是,直接用tail
函数来处理列表是不方便的。 当您开始编写复杂的macros或者甚至是macros生成的macros时,它会变得显着。 所以这里是“quasiquotation”,字面意思是“几乎是一句话”。 通常quasiquotation看起来像简单的引语(但与另一个引号):
`(defn f [xy] (+ xy))
但它是更强大的东西。 在quasiquoted列表中,您可以用外部范围的实际值replace任意元素,从而获得类似于模式的东西。 例:
(let [z 10] `(defn f [xy] (+ xy ~z)))
在这里,我们将值10
绑定到z
variables,然后我们用quasiquote来代替它。 这个expression式产生
'(defn f [xy] (+ xy 10))
这是一个简单的例子。 Lisp语言允许用quasiquotes做许多其他有用的事情。
这个概念已经转移到支持语法树操作的其他语言。 例如,这里的Haskell工具是模板Haskell,它完全支持准分类,即创build模板并使用外部范围的值填充它们。 在具有复杂语法的语言(如Haskell)中,准和简单引号几乎成为操作语法树的唯一理智方法。
UPD:嗯,似乎在Haskell这是比简单的替代更复杂的function。 Haskell中的Quasiquote看起来像可以由用户定义的expression式的任意转换器和评估器。
这些概念存在于Lisp语言及其变体中。
在这些语言中,只要解释器看到一个列表(abc ... z)
,就通过对其他元素b ... z
应用a
来评估它。
如果你想要一个列表不被评估(因此被解释为一个列表),你必须引用它。 例如, '(abc)
评估为包含三个元素的列表,而不是应用于b
和c
。 你可以看到报价停止评估 。
现在quasiquotation的行为像引用,除了你可以恢复列表的部分内的评价。 你用后面的撇号quasiquote`,并且允许某些子expression式用逗号运算符不加引号 (至less在Scheme中,我不知道其他Lisp变体)。 例如
`(a ,(bc))
(bc)
的评估结果评估为具有两个要素的列表。
这对于构build模板来说非常有用,在这些模板中,您可以通过取消引用来填充空洞 示例(从那里取得 ):
(define (create-shipping-employee-association name) `((name ,name) (employee-id-no ,(get-next-employee-id!)) (department shipping) (hire-date ,(get-day) ,(get-month) ,(get-year))))
在Nemerle中,一个准引文是( http://nemerle.org/metaprogramming.pdf ):
“
元语言是编程这种操作的语言。 它通常有自己的语法来描述对象语言的各种结构。
例如,在我们的系统中:
<[ 1 + f (2 * x) ]>
表示expression式的语法树:
1 + f (2 * x)
这个想法被称为准引用。
前缀准来自于将元语言expression式的值插入引用的上下文中的可能性。
如果g(y)
是这样一个expression式,我们可以写:
<[ 1 + $(g(y)) ]>
它描述了一个语法树,其第二部分被g(y)
的评估结果所取代,
“
一个报价只是一个string文字。 准引号在某种意义上代表input,而不是被编译的代码; 他们只是用一种更容易在编译过程中操作的forms(一种抽象语法树,可以用比文本操作更安全的各种方式)来表示它。
准基本上意味着您可以在报价单内放置一个美元符号,并再次切换到非引用的代码:
<[ WriteLine( $(ReadLine()) ) ]>
这将在运行时输出一个string在编译时input(实际上,我不认为这将工作,例如在Visual Studio中,因为ReadLine需要控制台input;但你可以从文件,networking等读取)。