面向语言编程
面向语言编程
我们经常听说面向过程编程、面向对象编程,偶尔会听说面向切片编程。那么面向语言编程又是什么呢? 这里是我个人的一些见解。内容仅供参考。
所谓面向什么编程,就是通过那种东西来对问题建立模型并加以解决。
例如说面向过程编程,我们考虑的便是用过程,也可以说是做事的步骤,来描述问题。 首先事情总是会一件一件做完的。其次做事的过程中会考虑到要不要做,做几次,于是我们便有了分支结构和循环结构来描述。 最后我们也可以把经常会一起做的几件依序完成的事组合成一个过程。例如泡茶这个过程就包含了烧开水,冲茶等步骤。 烧开水这个过程就包含了往水壶里倒水,加热等步骤。
例如说面向对象编程,我们考虑的是用对象,也可以说是客体或者物体,来描述问题。 首先物体具备属性,例如叶子有颜色,鸟有叫声,车有轮胎数量等。其次物体具备行为。例如鸟可以叫,人可以开车,灯可以开关。 我们要做的就是把问题建立成一个个物体进行行为的这么一个模型。
那么面向语言又如何呢?语言有语法,有语义,有的可以精简或者说运算。我们便是通过这些来对问题建模。
例子
鸡兔同笼
让我们解决下最基础的鸡兔同笼问题。根据《孙子算经》,鸡兔同笼,共35头94足,有多少鸡多少兔呢?
我们选择用矩阵来描述这个问题。我们会得到如下一个二元一次方程组的增广矩阵:
$$ \begin{pmatrix} 1&1&35\\ 2&4&94 \end{pmatrix} $$
显而易见数学的语言是有语法的。比如!@#¥%……&*()肯定就不符合矩阵的语法。 如果它有四或更多列,它虽然是个合法的矩阵,但它不符合语义,因为它将不再是个二元方程组的增广矩阵。 它可以化简,化为行简形的: $$\begin{pmatrix} 1&0&23\\ 0&1&12 \end{pmatrix}$$ 而在化简后,我们也得到了我们所需要的结果。
ScalaTest
ScalaTest是Scala的一个测试库。它具有一个领域专用语言,可以写出如下形式的断言:
result should be (10)
它通过宿主语言Scala的类型系统来定义自己的语法。
例如对于BeWord
,有函数a
来接续匹配器来断言种类,例如result should be a (negativeNumber)
;
或者直接跟一个值来断言值,例如result should be (10)
;
也有函数thrownBy
来接续可能抛出异常的表达式,例如exception should be thrownBy (someExpression)
。
它的语义通过命名清楚地表现了出来。
而它简化的结果,或者说运算的结果,要么断言通过,要么断言失败抛出异常。
面向语言编程的意义
面向语言编程就是通过定义一个语言来更清楚地描述问题,通过领域专门的词汇等使得表达更精简或者更易懂,同时通过语义验证和化简运算将该领域的知识融入进语言中。
这样的例子有许多。 比如Markdown相比HTML而言能更加精简地表达写作时一般用到的格式,并且增强了可读性; 比如SQL就是个增强了可读性以及易学习的查询用领域特定语言; 比如Coq和Agda相比其它语言就更能兼顾证明定理。
领域特定语言一般大致分为两种。一种是完全独立,语法自由,但是较难与其他语言混合。 另一种则嵌入在其它语言中,利用灵活的宿主语言来定义,语法部分受限,但因为本身便是宿主语言, 因此可以与其他同宿主语言的语言直接混合。两种方法各有优缺点。