[NAME]
ALL.dao.type

[TITLE]
数据类型和类型标注

[DESCRIPTION]

道语言支持可选(混合)类型系统,允许声明带或者不带类型标注的变量。 当一个变量的声明不带类型标
注时,它的类型一般可根据一些规则被自动地推导出来。 对于有类型标注或能被推导出类型的变量,编译
时的静态类型检查将被执行, 否则类型检查将回推迟到运行时执行。

 1  类型标注    
 1  类型标注    
 1  类型标注    

道里面的类型标注都是放在变量名,参数名或成员域名后面, 并用冒号与名称分开: 
     
   1  名称: 类型
   2  名称: 类型 = 值
   3  
   4  routine MyFunction( 名称: string, index: int = 1 ) { ... }
   5  
   6  class Klass
   7  {
   8      var 名称: 类型 = 值
   9  }
     


多个变量可被同时声名有同样的类型和初始值: 
     
   1  名称1, 名称2 : 类型
   2  名称1, 名称2 : 类型 = 值
     


 2  数据类型    
 2  数据类型    
 2  数据类型    

道支持丰富的数据类型,以便方便的开发程序。

 2.1  基本类型 

下表中所列的是基本道语言基本数据类型:
                                 
  类型名    类型描述               
  none     空值类型               
  bool     布尔类型               
  int      整数类型(64位)         
  float    双精度浮点数类型(64位)  
  complex  双精度复数类型          
  string   字符串类型             
  enum     枚举符号类型            
                                 
尽管enum是一个基本类型,它的类型名可变,并可包括它所含的符号名称。 例如: 
     
   1  var name: string
   2  var state: enum<off,on> = $on
     


 2.2  复合类型 

下表所列为道语言里的关键复合类型:
                                          
  类型名                        类型描述    
  array < 元素类型 >            数组类型    
  tuple < 元素类型或名字加类型 >  元组类型    
  list  < 元素类型 >            列表类型    
  map   < 键类型, 值类型 >       关联表类型  
                                          
这些模板类型可有类型参数,这些类型参数通常表示这些复合类型所能装的元素类型。 例如: 
     
   1  array<int>         # 可装整数的数值数组;
   2  list<string>       # 可装字符串的列表;
   3  map<string,int>    # 可装键为字符串类型值为整型的关联表;
   4  tuple<string,int>  # 可装一个字符串和一个整数的元组;
   5  
   6  # 下面的这个元组类型可装带名字的元素:
   7  # 它的第一个元素是名为"name"字符串类型;
   8  # 它的第二个元素是名为"index"整数类型;
   9  tuple<name:string,index:int>
     


下面是一些用这些类型做类型标注的例子: 
     
   1  var vector: array<int> = [ 1, 2, 3 ]
   2  var tuple1: tuple<string,int> = ( "abc", 123 )
   3  var tuple2: tuple<name:string,index:int> = ( 'abc', 123 )
   4  var names:  list<string> = { "Joe" }
   5  var table:  map<string,int> = { "abc" => 123 }
     


 2.3  占位符类型 

占位符类型的类型名都以@前缀开头,表示待定义的类型。 在一个局部环境中(如单个复合类型和函数原
型等),同名的占位符类型表示同一个类型。 它们通常被作为类参数用在类模板类型里,或这些类型的方
法原型里。 这样这些类型和它们的方法都变得通用化,并可正对特定的类型参数特例化。

例如,列表类型就被声明为list<@T=any>。 这里any是列表的缺省类型参数。 这意味着无参数的list<>类
型将等同于list<any>类型。 列表的一个方法的原型如下: 
     
   1  append( self: list<@T>, item: @T, ... : @T ) => list<@T>
     
在这个原型里,所有占位符类型@T都表示同一个类型。 这意味着对于类型list<@T>(以@Tstring 作为
例子),这个方法只能将类型为@T (string) 的值附加到list<@T>类型的列表里。

这里是个更简单的例子: 
     
   1  tuple<@T,@T>
     
这表示这个元组类型只能装两个同类型的值。

 2.4  任意类型 

特殊类型any可用来表示任意类型。 将一个变量声明为any类型将有效地将这个变量的静态类型检查禁止
。

 2.5  值类型 

道里面的另一个特殊类型是值类型。这种类型除了定义普通类型的类型信息, 它还定义了一个特定的常
数值。当一个值匹配到此类型时,不但要类型匹配, 而且还要值匹配。

前面提到的空值类型none既被定义为一个值类型, 一般只有空值none本身能匹配到这个类型。 不过为了
方便起见,封装空指针的C类型也能匹配到这个空值类型。 空值类型可象其它类型一样在任意地方使用,
但它最通常的用途是用在 多型(variant)类型里,表示这个类型的变量或参数可以是空值。

其它的值类型不能象普通类型那样用在任意地方, 它们主要是用作复合类型的类型参数。例如: 
     
   1  tuple<1,2>
     
表示一个第一个参数只能装整数1和第二个参数只能装整数2 的元组类型。 值类型的这种用法主要是对
于封装C++模板类型有用。

 2.6  多型(Variant)类型 

多型(variant)类型是一种表示多个可能类型的类型。 这种类型的声明是通过将多个类型用分隔符|连起
来声明。 被标注为多型类型的变量可保存这个多型类型所表示的任意一种可能类型的值。 例如: 
     
   1  var intstr : int|string = 123
   2  intstr = 'abc'
     

在道里,只有被标注为空值类型none或未定义的占位符类型或任意类型 的变量能保存空值。但有时已知
有些其它特定类型变量的值可能为空值, 为了让道的类型系统能处理这种情况而不报错,这些变量的类
型必须被标注为 包含none的多型类型。 例如: 
     
   1  routine FindWord( source: string, word: string ) => int|none
   2  {
   3      var pos = source.find( word )
   4      if( pos < 0 ) return none
   5      return pos
   6  }
   7  
   8  var pos1 = FindWord( "dao language", "dao" )  # pos1 = 0
   9  var pos2 = FindWord( "dao language", "lua" )  # pos2 = none
     
详情请参看dao.type.variant 2.7  函数类型 

函数类型由关键词routine和其它类型构成。 这种类型一般由函数和方法的声明自动生成。 例如: 
     
   1  routine Test( name: string, value = 123 )
   2  {
   3      return value * 10;
   4  }
   5  io.writeln( std.about(Test) )
   6  # Output: Test{routine<name:string,value=int=>int>}[0x7f9ef1c50340]
     
输出里的routine<name:string,value=int=>int> 就是为Test函数自动生成的函数类型名。 这里: 
  *  name:string : 第一个参数的类型信息,表示第一个参数名为name, 且是字符串string类型;
  *  value=int : 第二个参数的类型信息,表示第二个参数名为value, 且是整数int类型,并且带有一
     个缺省参数值;
  *  =>int : 被推导出的返回参数类型; 


对于代码块方法,它们的类型名有额外的部分。 例如,列表类型的代码块排序方法有如下原型: 
     
   1  sort( self: list<@T>, part = 0 )[X: @T, Y: @T => int] => list<@T>
     
它的类型名为: 
     
   1  routine<self:list<@T>,part=int=>list<@T>>[X:@T,Y:@T=>int]
     
这里[X:@T,Y:@T=>int]相对于普通函数类型的额外部分。 它表示这个方法的代码块可以使用两个类型为
@T的参数, 并且应该产生一个整数作为代码块的返回结果。

当然函数类型也可被显示声明。例如变量就可按以下方式被标注为一个函数类型: 
     
   1  var myfunc: routine<p1:string,p2=int=>int>
     


 2.8  泛型类型 

道语言里的如列表和关联表等标准复合(容器)类型被作为泛型支持。 这种泛型支持也能被用户定义类型
使用。 不过这种泛型类型只能在C模块里以由C实现的用户类型定义。 这种用户定义的类型,其定义方式
和使用方式于内置的标准泛型类型 基本一直。

这种泛型类型的一个典型例子就是未来值类型mt::future<@V>。 尽管future是一个内置的类型,但用户
可以以同样的方式定义 其它泛型类型。 详情请参看daovm.interface.extending里关于定义用户类型的
技术。



 2.9  类型别名 

道里面用户可以按以下语法给每个可显示声明的类型定义别名: 
     
   1  #TypeAliasing ::= 'type' Identifier '=' Type
   2  type alias = another_type
     
For example, 
     
   1  type StringList = list<string>
   2  type Point3D    = tuple<x:float,y:float,z:float>
     



[STRUCTURE]

dao.type--| dao.type: 数据类型和类型标注 (73.3 KB)
          |--bool-----| dao.type.bool: 布尔类型 (0.3 KB)
          |--int------| dao.type.int: 整数类型 (0.6 KB)
          |--float----| dao.type.float: 单精度浮点数类型 (0.6 KB)
          |--complex--| dao.type.complex: 复数类型 (0.6 KB)
          |--enum-----| dao.type.enum: 枚举符号类型 (5.0 KB)
          |--string---| dao.type.string: 字符串类型 (24.7 KB)
          |           |--pattern--| dao.type.string.pattern: 字符串模式匹配 (11.4 KB)
          |           |--method---| dao.type.string.method: 字符串方法 (10.7 KB)
          |                         
          |--array----| dao.type.array: 数值数组类型 (6.6 KB)
          |           |--method--| dao.type.array.method: Array methods (4.7 KB)
          |                        
          |--list-----| dao.type.list: 列表类型 (12.9 KB)
          |           |--method--| dao.type.list.method: 列表方法 (12.0 KB)
          |                        
          |--map------| dao.type.map: 关联表类型 (7.5 KB)
          |           |--method--| dao.type.map.method: 关联表方法 (5.9 KB)
          |                        
          |--tuple----| dao.type.tuple: 元组类型 (1.7 KB)
          |--variant--| dao.type.variant: 多型(Variant)类型 (3.3 KB)