用函数表达复合句

概述

为保证通用性,介绍文法设计时我主要只是约定两种形式文法间的转换规则,而不对句子的推理规则等语义内容进行设定。这两种文法本文称作函数文法和运算符文法。函数文法更适合进行分析或绑定定义;运算符文法则是序列化的、更适合绑定语音文字等形式——通常减少括号这样的辅助性的组分而具有更高的信息密度。

函数文法中的句子是一个可嵌套的函数表达式,其中每个函数的求值都会给出一个返回值和副作用返回值主要用于传递变量,而副作用则用于产生句子,它们的结合将提供一种将表达式解嵌套(也就是说,将一个复合句分解为多个简单句)的方式。

*表达式

这里不赘述什么是表达式以及函数求值(坑)。在本文中,嵌套的表达式用如下的记法 [1]

f[g[x, h[y]], z]

它具有下图所示的结构。

graph f-->g f-->z g-->x g-->h h-->y

这树图中的叶子 x,y,z 称为原子(或者原子表达式); h[y] g[x, h[y]] f[g[x, h[y]], z] 则都是一般表达式; f,g,h 则称为(某个一般表达式的)头部。

*函数与求值

简单来说,一个函数是一个黑盒子,它吞吃一些输入(称为函数的参数),然后按照这个函数的定义做一些事情,并吐出一个输出(称为函数的返回值)。一个函数允许的参数数目在定义时就已固定的,这个数目称为函数的元数。

假设有一个嵌套的函数表达式 Record[FromHour[AddOne[6]]] ,表达式头 AddOne 是一个负责将传入的数字加一后返回的函数。在对这个嵌套函数进行求值时,这个返回值内部的 AddOne[6] 被重写为 7 ,于是得到 Record[FromHour[7]] ,此时求值继续进行,其中的 FromHour[7] 按定义被重写为 "A.M. 7:00" ,最后 Record["A.M. 7:00"] 使得这个时间数据被记录进硬盘或者读者的脑中(就这一目的而言,这整个表达式本身的返回值已不重要)。

在这个求值过程中,硬盘的状态发生变化,这一变化由 Record 函数直接负责,它通过返回值以外的方式对我们所关心的东西造成了影响。而 FromHour AddOne 这两个函数对硬盘的影响方式仅仅是通过返回值来实现的,这种情况下我们说它们是无副作用的函数。之后我们会看到反作用的概念会在绑定语义解释时出现。

嵌套函数与复合句分解

我们现在将

苏格拉底是古希腊哲学家

用这种函数文法记述为

kuli1[filo1[soke]]

其中:

  • soke 是这样一个原子表达式(常量),即 苏格拉底

  • filo1 是这样一个一元函数:如果它的参数为 x ,则它指示读者应记录这样一个断言 x 是哲学家 ,并将这唯一的参数 x 作为返回值。

  • kuli1 是这样一个一元函数:如果它的参数为 x ,则它指示读者应记录这样一个断言 x 是古希腊人 ,并将这唯一的参数 x 作为返回值。

于是在求值过程中,有以下断言被记录:

  • 苏格拉底是哲学家

  • 苏格拉底是古希腊人

讨论

在上一节中,我们通过写下一个含有变量的模板句子 [2] 来定义谓词(即 谓述 ),然后通过指定返回值和副作用来衍生出一个函数,返回值的设计是用于组合简单句,而其副作用则是关于填充后的模板句子的一个言语行为。这是一种本文用于辅助叙述、且可令一些读者感到熟悉的语义绑定方式,但函数模型不限于此种方式,而可能兼容于许多其他语义框架。