English  
     
 

 

主页   新闻   白皮书   文档   出版物   下载   源码   方案   资质
 
 
     
     
  主页| 文档| 目录| 前章| 后章    
       
     
     
 

第三章 类型与变量

    类型(Type)是程序设计语言的基本概念。类型是存储在计算机内存中数据的抽象,它决定了数据表示方式和可对其进行的运算。Fuxi是一种强类型(strongly typed)语言,这意味着在编译时就确定了每个变量或表达式的类型。强类型有助于在编译器检查错误。类型限制了变量所能持有的或表达式所能产生的值的类型,也限制了能够施加在这些值上的操作,并且决定了操作的意义。

    Fuxi的类型分为两类:基本类型(Primitive Type)和引用类型(Reference Type)。基本类型指整数类型(其中包括byte、short、int、long等带符号整数类型,以及对应的无符号整数类型ubyte、ushort、uint、ulong)、浮点类型(float和double)、bool类型(也称逻辑类型)和char类型。Fuxi的引用类型指类类型(class type)、接口类型(interface type)、代理类型(Delegate Type)及表(list)和数组(array)类型。对象在Fuxi中是指类类型的实例或表、数组。引用类型的值为对对象的引用。Object类是所有对象(包括表和数组)的基类。

§3.1 类型的种类和值

    Fuxi语言包括两种数据类型:基本类型和引用类型;同时也具有这两种类型的值,即基本数值和引用值,他们可以存储在变量中,作为参数进行传递,作为方法的返回值,以及作为运算符的运算参量等。

<类型>定义为

<基本类型>
<引用类型>
<子类型>

    类型定义了该类型的数据的取值范围,而该范围的一个子集称为类型的一个子类型。子类型仅在变量声明中使用,对变量的取值范围进行限制;但在表达式中,子类型的数据会自动转换成该子类型所对应的类型。

    此外,还有一种类型称为空类型(null type),它是表达式null的类型,没有类型名。因为空类型没有名称,当然也就不可能声明一个空类型的变量,也不可能把某个表达式的值转换成空类型。空引用(null reference)是空类型唯一可能的值。空类型的值可以转换成任意引用类型。

§3.2 基本类型

    基本类型是Fuxi语言预定义的,并且由关键字命名的类型。

<基本类型>定义为

<数值类型>
bool
char

<数值类型>定义为

<整型>
<浮点型>

<整型>定义为

<有符号整型>
<无符号整型>

<有符号整型>定义为以下关键字之一

byte short int long 

<无符号整型>定义为以下关键字之一

ubyte ushort uint ulong

<浮点型>定义为以下关键字之一

float double

    基本类型包括数值类型、字符型和布尔型(逻辑型)。基本类型的数值都是独立的,不依赖于其他类型的数值而存在。这三种类型的数据之间不可进行类型转换,例如,不能将数值型的数据转换成字符型或布尔型。数值类型又包括整型(Integral type)和浮点型(Floating-point type)。

§3.2.1 整型

    整型又分为有符号整型(Signed integral type)和无符号整型(Unsigned integral type)。其中有符号整型包括:byte、short、int和long,它们分别表示8位、16位、32位和64位带符号的二进值补码整数;而无符号整型包括:utype、ushort、uint和ulong,分别表示8位、16位、32位和64位无符号的二进制补码整数。

    整型数值的范围如下表所示:

序号

保留字

字节数

取值范围

 1

 byte

 1

 -128 ~ 127

 2

 ubyte

 1

 0 ~ 255

 3

 short

 2

 -32 768 ~ 32 767

 4

 ushort

 2

 0 ~ 65 535

 5

 int

 4

 -2 147 483 648 ~ 2 147 483 647

 6

 uint

 4

 0 ~ 4 292 967 295

 7

 long

 8

 -9 223 372 036 854 775 808 ~
  9 223 372 036 854 775 807

 8

 ulong

 8

 0 ~ 18 446 744 073 709 551 615

    Fuxi语言在规定整型的数据表示和数值范围的同时,也规定了对这些整型数值的运算。运算根据参量的个数可以分为单元运算和二元运算等。整型的二元运算要求两个参量具有相同的类型。

    整型运算包括:

  1. 数值运算:

  2. 比较运算:

  3. 类型转换:

§3.2.2 浮点型

    浮点类型用来近似表示数学上的实数,Fuxi中浮点根据其数据精度分为单精度浮点数(float)和双精度浮点数(double)两种。它们的数据长度及数值范围在上表的第9和第10行列出。

    Fuxi中经常使用float类型,其处理速度快、占用空间小。当出现以下情况时应当使用double类型:

  1. 当处理的数值小于等于1.0e-38或大于等于1.0e+38时;

  2. 当处理高精度的数据时;

  3. 因高级CPU的优化,其double型数的处理速度较float型快时;

  4. 需要调用Fuxi的数学函数库时。Fuxi的数学函数库中几乎所有的数学函数都使用double型。

§3.2.3 字符型

    Fuxi的字符采用Unicode字符集,类型长度为16比特位,即两个字节。Unicode字符集包括汉字、希腊字母、拉丁字母、阿拉伯文、数学符号等几乎所有的语言符号。操作符==用来比较字符的相等,操作符++是找某字符在Unicode集中的下一个字符。

§3.2.4 布尔型

    布尔类型是一种逻辑类型,只包含两个值true和false。true和false是两个保留字,分别用来表示真和假。
对布尔型数据进行的操作称为逻辑操作,它们包括:逻辑与(也称析取)、逻辑或(也称合取)和逻辑非。布尔型数据及其逻辑操作是Fuxi规则的基本成分。

§3.3 引用类型

    引用类型(Reference Type)表示对某一数据对象的引用。Fuxi中基本类型所引入的数据对象通常被放置在执行堆栈(Stack)中,而引用类型所引入的数据对象总是存放在堆(Heap)里,而执行堆栈中保存该对象的引用。

§3.3.1 Object类型

    对象(Object)类型是所有其它类型的基类。Fuxi中的所有其它类型都是直接或间接地从Object类型派生出来的。Fuxi中Object对应于抽象机中的GOBJ。Object类型定义在Fuxi的基本类库lang中。

§3.3.2 class类型

    类(class)是一种数据结构,它包括属性(常量、字段)和方法(函数、子句、触发器)。类支持继承。在Fuxi中类也是一个对象,称为类对象(Class Object),它是某一类型对象的模板(Template)。类对象包含CreateObject和GetTypeInfo两个方法,分别用于创建一个新对象和获取该类的类型信息。类类型将在第5章中详细介绍,这里我们给出一个类的例子。

import fuxi.*
class Point
{
    public int x, y
    public Move( int x, int y ) = 
    {
        this.x += x
        this.y += y
    }
}
class Circle : Point
{
    public int radius
    public Circle( int r ) = this.radius := r
}
public class CircleApp : Applet
{
    Circle c( 10 )
    public Activate( ) =
    {
        c.Move( 100, 100 )
        Console.Println( "C的圆心为:(" + c.x + ',' + c.y + ')' )
    }
}

执行结果为:

C的圆心为:(100,100)

§3.3.3 接口类型

    接口(interface)其实就是一种大家共同遵守的协议。实现某个接口的类必须遵守此协议。一个接口可以派生于多个接口,同时,一个类也可以实现多个接口。接口将在第7中进行详细定义。

§3.3.4 表类型

    表(List)是Verga的一个重要的数据结构。表是某一数据类型的数据的集合。表可以是空的,也可以通过insert方法向表中的某一位置插入一个元素,也可以通过delete方法删除表中的某一元素;可以通过下标运算或take函数访问表中的元素,通过scan函数来枚举表中的元素。

§3.3.5 数组类型

    数组(Array)是一个特殊的表,元素的个数是预定的。当数组被创建时,数组中的元素也同时创建。和表不同,数组的大小是固定的,不能插入或删除元素。

§3.3.6 代理类型

    Fuxi语言是面向对象的程序设计语言,Fuxi中函数总是某个对象或类的方法。同时Fuxi又是一个函数型语言,函数型语言经常要求可以以函数为参数形成新的函数,这种以函数为参数的函数称为高阶函数(High-order Functions)。为了能够向函数传递一个函数作为参数,Fuxi提供了代理(delegate)类型,它相当于C++中函数指针。

    代理类型有两种情况,一种是引用对象的一个静态方法,另一种情况是引用一个对象的及此对象的实例方法。

§3.4 变量

    我们在编制程序来解决问题时,必须对一些数值进行操作。而一个问题的不同特例可能要用到不同的值。如果我们在程序中用一个特定的值解决问题的一个特例的话,当需要解决另一个特例时,就不得不修改程序里的那些特定的值。由于上述原因,大多数程序都编制成能处理各种特例的通用程序。程序设计语言为了能支持通用程序设计,就必须允许程序员用变量名来代替任何数值。这样,在程序中可以用变量名来代替特定的数值,而在处理不同特例时只需要简单地改变输入值以使变量名与该值对应,而不必改动程序。

    在Fuxi中,一个变量既可以表示一个特定的存储位置,也可以用来表示与一个表达式之间的约束关系(Binding)。变量在创建之初是一个未知量,它既可以被赋予一个特定的数值,也可以被约束为一个表达式。
若一个变量的值尚未确定,我们称它是自由变量(free variable);若已被赋予了一个特定的数值,则称为引用变量(reference variable);若被约束为一个表达式,我们称它为约束变量(bound variable)。

§3.4.1 变量的赋值与约束

    Fuxi中赋值与约束是两个重要的概念。

    赋值(Assignment)是将某一特定的数值存放到变量所代表的一个特定的存储位置的过程。和C++、JAVA等语言不同的是,Fuxi的赋值是一个bool型函数,如果赋值成功,返回true,否则返回false。程序对变量进行赋值时,首先要检查该变量能否被赋值。一个变量能够被赋值的条件是:变量是自由变量或引用变量,同时待赋的值与变量有相同或兼容的类型。我们不能对约束变量赋值。
对变量的赋值,采用赋值符号(:=)。例如,

x := 100

    除了‘:=’给变量赋值外,Fuxi语言还提供以下的自运算赋值形式:

赋值

实 例

等价形式

 +=

 x += 10

 x := x + 10

 -=

 x -= 10

 x := x - 10

 *=

 x *= 10

 x := x * 10

 /=

 x /= 10

 x := x / 10

 %=

 x %= 10

 x := x % 10

 &=

 x &= 10

 x := x & 10

 |=

 x |= 10

 x := x | 10

 ^=

 x ^= 10

 x := x ^ 10

 &&=

 x &&= y

 x := x && y

 ||=

 x ||= y

 x := x || y

 ++

 x++

 x := x + 1

 --

 x--

 x := x - 1

    约束(Binding)是将一个变量同一个表达式关联起来,在程序的其它地方对该变量的引用也就等同于对与其关联的表达式的引用。一个约束变量在其被释放(unbind)之前,其值是固定的,也就是它所代表的表达式的值。我们不能对一个约束变量赋值,也不能再把一个约束变量约束成另一表达式。

    我们可以在变量的声明中,通过等号(=)将其约束为一个表达式,例如:

int x = Console.Readln().ToInteger()

    另外,程序中在调用对象的方法时,通过模式的匹配和合一,将模式中的形式参数约束成实际的参数表达式。关于模式的匹配与合一,我们将在以后的章节中讨论。

    值得注意的是,赋值是把一个值赋给变量,赋的是“值”,因此赋值前需要先对表达式进行计算,把计算的结果赋给变量。而约束是把同某一表达式的等价关系赋给变量,赋的是“约束关系”。在这种意义上,我们也可以把约束理解成一种“关系”赋值。

§3.4.2 变量声明

    Fuxi是一种强类型语言,每个变量都关联一种类型,该类型要么是基本类型,要么是引用类型,有时也称这种类型为编译时类型。变量的类型是在变量声明时,由程序员指定的。在程序的执行过程中变量的类型不能改变。变量的值(假如有的话)总是与其类型相一致的。

    变量的声明形式如下:

<类型> <标识符> [<初值定义>]

    其中<类型>为表示基本类型的保留字(如int)或者为引用类型。<标识符>就是变量名。<初值定义>是可选项。<初值定义>的定义形式为:

= <表达式>     
:= <表达式>

    前者表示将变量约束为等号(=)后面的表达式,而后者则将<表达式>的值赋给变量,作为该变量的初始值。

    以下是两个变量的声明:

double y = sin(x)
int z := 100

    在一个声明语句中,可以同时声明几个变量,各变量之间采用逗号(,)分隔。这些变量将具有相同的类型。例如:

int w, x := 100, y = 2 * x, z = x + y

    本例中我们同时声明了四个int型变量w、x、y和z。其中w为自由变量,x为引用变量,而y、z为约束变量。

§3.4.3 变量计值

    无论变量处于什么状态,当在被运算符或函数调用等引用并取值时,它必须提供一个与其类型相一致的数值。这一过程我们称为变量的计值(Evaluation)。

§3.4.3.1 自由变量的计值

    当变量处于自由状态时,如果需要取值时,自由变量将提供其类型的缺省值。类型的缺省值见下表:

类型

缺省值

 byte

    0

 short

    0

 int

    0

 long

    0

 ubyte

    0

 ushort

    0

 uint

    0

 ulong

    0

 float

    0.0

 double

    0.0

 char

    \u0000

 bool

    false

 引用型

    null

§3.4.3.2 引用变量的计值

    由于引用变量的存储单元内,已经保存有该变量的值,因此当对值变量取值时,它便直接将其存储单元内的数值返回给取值者。

§3.4.3.3 约束变量的计值

    我们已经知道约束变量的值就是其所关联的表达式的值,但是何时才对表达式进行计算求值呢?Fuxi语言是一个惰性语言,仅当对约束变量进行取值操作时,才对表达式进行计算求值。我们来看一个例子,

import fuxi.*

public active class FreeVars: Applet
{
    public Activate() = 
           let
           {
                int x, y := 100, z = x +y
           }
           in 
           {
                x := x + y
                Console.Println( "z = " + z )
           }
}

    这个程序执行的结果为:

z = 200

    本例中,我们使用了let语句,Fuxi中使用let来为表达式定义局部变量。关于局部变量,在以后的章节中我们还将详细讨论。

    在这个程序中的let段内,我们定义了三个int型变量x、y和z。其中x为自由变量,y是一个初值为100的值变量,而z为一个约束变量。

    当计算x + y时,需要分别对x和y进行取值,这时x是自由变量,计值为0;y是值变量,其值为100。因此x + y结果为100。

    当计算"z=" + z时,需要对z取值,这时z是一个约束变量,尚未计值。系统取出z所约束的表达式x + y进行计算,这时x和y均为值变量,值都是100,因而z的值为200。

    值得注意的是,Fuxi中约束变量一旦被计值,该值将被保存在变量的存储单元内,并保持此值不变。当下次再对该约束变量取值时,系统将直接返回该值给取值者,而无须再对表达式进行计算。

    我们再来看一个例子:

import fuxi.*

public class BoundVars: Applet
{
     public Activate() =
            let
            {
                 int x := 100, y = x + 100, z = x + y
            }
            in
            {
                 x += y
                 Console.Println( "z = " + z )
            }
}

    程序的执行结果为:

z = 500

    程序中出现了两次对约束变量y的引用。当执行x += y时,这是y尚未计值,因此要对y进行计值,计算x + 100的值,而此时x的值为100,所以计值后变量y的值被设定为200。变量x经+=赋值后,变成300。当程序对变量z进行计值时,又需要引用x和y,注意这时x的值为300,而y的值仍为200。因而最后的结果为x + y = 500。

§3.4.4 变量状态的测试

    前面我们已经讨论过变量的状态,Fuxi的变量可以分为:自由变量、值变量和约束变量。在程序中我们有时需要知道一个变量的当前状态,Fuxi为我们提供了一个变量状态测试函数test。test是Fuxi的一个保留字,test函数的原型为:

test( <变量名> ) = int

    test函数的返回值是一个整数,表示变量的状态:

0: 自由变量
1: 值变量
2: 约束变量
3: 已计值的约束变量

§3.5 类型转换

    Fuxi是强类型语言,对每个操作Fuxi都要做类型检查。对于类型不符的操作,要么产生错误信息,要么做类型转换(Type Conversion)。Fuxi语言中的类型转换有三种情况,即自动转换、强制转换和方法转换。其中数值之间的转换可以用自动转换和强制转换,方法转换引用类型和数值类型之间或引用类型同引用类型之间的转换。这里我们只讨论自动转换和强制转换,而方法转换将在以后章节中讨论。

§3.5.1 自动转换

    基本类型的数据在一定条件下,自动地升级为具有更高数据精度的类型,称为数据类型之间的自动转换(Coercion),也称为隐式转换(Implicit Conversion)。自动数据转换的基本原则是不丢失信息。数据类型的精度高低如下:

byte ubyte short ushort int uint long ulong float double

低 高

    看下面的例子:

byte b := 8
long l := 64L
float f := 32.0f

    在表达式

b + l + f

中b、l都自动升级为float型,最后表达式类型为float。

§3.5.2 强制转换

    Fuxi可以采用强制类型转换的方式,将一种类型的数据转换为另一种类型,强制转换的文法为:


(<类型>)<表达式>

    文法中<类型>必须是基本类型之一,并且一定要用括号括起来。强制转换也称为显式转换(Explicit Conversion)。

    例如:

(int)3.14 // 结果为3
(char)(12.4 + 55) // 结果为'c'
(int)32.4 // 结果为32
(long)-100.5 // 结果为-100L

    例如:

long big := 123
short small := (short)big // long转换为short
double d := 123.456
long l := (long)d // double转换为long

 

 
   
   
   
 

友情链接:深圳市触品科技有限公司 www.touchbuy.cn

友情链接:深圳市趋高智能系统有限公司 www.hitrend.com

友情链接:深圳市触品便利店有限公司 www.touchstore.cn

关于我们  联系我们  加入我们

©2006-2019 fuxi.org, 版权所有. 粤ICP备11003046号