在拟抽样中“准”的含义是什么?

一些像Haskell(或Nemerle)这样的语言有quasiquotations 。 我不知道“准”是什么意思,如果没有“准”部分也存在“引用”。

我相信这个概念来自Lisp语言。

用Lisp编写的程序由一系列列表列表组成,如下所示:

  (defn f [xy] (+ xy)) 

由于这种一致性,可以表示和处理这样的代码作为数据,所以上面的字符序列被解释为文字列表。 这是Lisps的一个非常有用的function,它们的特色之一。 为了方便,Lisp语言允许“引用”有意义的序列,将它们从定义和expression式转换为列表。 它看起来像这样:

  '(defn f [xy] (+ xy)) 

在这种情况下,它是一个文字列表,直接可用于使用Haskell的headtail类似物解构和其他方法。 所以,'quote'的意思是“从列表中创造一个文字值”。

但是,直接用tail函数来处理列表是不方便的。 当您开始编写复杂的macros或者甚至是macros生成的macros时,它会变得显着。 所以这里是“quasiquotation”,字面意思是“几乎是一句话”。 通常quasiquotation看起来像简单的引语(但与另一个引号):

 `(defn f [xy] (+ xy)) 

但它是更强大的东西。 在quasiquoted列表中,您可以用外部范围的实际值replace任意元素,从而获得类似于模式的东西。 例:

  (let [z 10] `(defn f [xy] (+ xy ~z))) 

在这里,我们将值10绑定到zvariables,然后我们用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)评估为包含三个元素的列表,而不是应用于bc 。 你可以看到报价停止评估

现在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等读取)。