Fuxi语言的方法模式
在函数定义中使用模式是函数型语言(如ML、Haskell等)中的一种流行方式。例如,Fibonacci函数可以表示为:
Fib( 0 ) = 1
Fib( 1 ) = 1
Fib( n ) = Fib( n – 1 ) + Fib( n – 2 )
模式是函数参量的结构形式,如例子中的0、1和n。在程序执行时,让函数的实参同模式进行匹配,如果参数同模式匹配,则执行此等式的定义体部分。
模式的使用可以让函数定义避免大部分的分支语句,从而使得定义体变得简洁、符合人们的思维习惯。Fuxi语言是一种说明性语言,Fuxi语言支持模式的使用。
1. 模式的定义
模式指Fuxi中方法的参量结构形式。模式是由常量、变量组成,其定义如下:
1) 常量是模式;
2) 形如<类型><标识符>的变量V为模式;
3) 形如<变量><比较运算符号><表达式>的带卫兵的变量VG是模式;
4) 表示对模式中变量引用的<标识符>是模式;
5) 如果P1和P2是模式,则P1, P2是模式;
6) []是模式;
7) [<模式>:<标识符>]是模式;
8) [<模式>:..]是模式。
在Fuxi的方法定义中,以下参量均是合法的模式定义:
1) 0
2) int x
3) int y > 0
4) 0, int x, int y > 0, x
int y > 0 就是一个带卫兵(Guard)的变量,只有那些大于0的常量才能同y匹配。
例如,符号函数Sign可以定义为:
Sign ( 0 ) = 0
Sign ( int x < 0 ) = -1
Sign ( int _ ) = 1
在Fuxi的模式中,‘_’是匿名变量,表示在后面的定义体中不使用的变量。
Equal函数可以定义为:
Equal ( int x, x ) = true
Equal ( int _, int _ ) = false
在这个例子中,第一个x定义了一个变量模式,而第二个x表示如果该参量与第一个参量相同。Equal( int x, x )和Equal( int x, int y == x )完全等价;而在Equal( int _, int _ )中,‘_’表示两个匿名参量。
2. 模式匹配
模式匹配/合一(Pattern Matching/Unification)是将一个方法调用表达式(可能已进行了部分计算)与一个模式进行比较,判断它们的结构是否一致,并把模式中的变量约束到表达式相应部分的过程。
当且仅当下面之一成立,表达式A和模式B是匹配的:
1) A=B;
2) B是变量或’_’,如果B带卫兵,且A的值满足B的卫兵的要求;
3) 设A=[a1, a2,…,ak],B=[b1,b2,…,bk],则ai与bi匹配;
4) 设A=[a1,…,ak,ak+1,…an],B=[b1,…,bk : X ],则ai=bi(i=1,…,k)。
如果A,B是匹配的,则称A是B的一个实例(Instance)。
在方法的调用过程中,Fuxi抽象机将调用方所提供的参数同方法的规则中的模式依次进行匹配与合一,第一个匹配上的规则将被取出执行。如果方法是函数,所匹配的规则定义体的值就函数的值;如果方法是谓词,且匹配的规则定义体的值为false,还将回溯继续寻找下一条匹配的规则;如果方法是触发器,匹配规则的值为false,系统将按对象的所属关系向外查找新的匹配触发器。
3. 模式的应用
这里给出两个模式应用的例子。
统计表中正整数的和Sigma函数可以定义为:
Sigma( [] ) = 0
Sigma( [int x > 0: T] ) = x + Sigma(T)
Sigma( [int _?: T] = Sigma(T)
统计表中的最大值的谓词可以定义为:
Max( [], int Z, Z )#
Max( [int x?: T], int nMax < x, int Z ) <- Max( T, x, Z )
Max( [int _ : T], int nMax, int Z ) <- Max( T, nMax, Z )
表达式Max( [9, 0, -1, 7, 3, 12, 6], -100, nMax )中的自由变量nMax将被约束为12。
下面是完整的Fuxi程序:
import fuxi.*
public active class PatternApp : Applet
{
Sigma( [] ) = 0
Sigma( [int x > 0: T] ) = x + Sigma(T)
Sigma( [int _: T] = Sigma(T)
Max( [], int Z, Z )#
Max( [int x: T], int nMax < x, int Z ) <- Max( T, x, Z )
Max( [int _ : T], int nMax, int Z ) <- Max( T, nMax, Z )
public Activate() =
let
{
int nMax
}
in
{
Console.Println( "SIGMA = " + Sigma([9, 0, -1, 7, 3, 12, 6]) )
if( Max([9, 0, -1, 7, 3, 12, 6], -100, nMax ) )
Console.Println( "MAX =" + nMax )
}
}
程序执行的结果为:
SIGMA = 37
MAX = 12