[NAME] ALL.dao.tutorial.types [TITLE] Essential Types [DESCRIPTION] Dao supports a number of essential types as built-in types to allow flexible use of them. These types include several number types, enum symbol, string, numeric array, list and map etc. 0.1 Numbers Dao has native supports for the following number types: int, float, double, complex and long. Integer and floating point numbers can be expressed in the same ways as in most other languages. Floating point numbers in Dao are parsed as double precision floating point numbers double by default. To explicitly express a single (double) precision floating point number float ( double), it is necessary to append a suffix F ( D) to a normally expressed number. The imaginary part of a complex number can be expressed as an int or float number with a C suffix. A general complex number can be expressed by combining an integer or a floating point number as the real part and an imginary part, which are both stored as double precision floating point numbers. long type represents arbitrary precision integers. They can be expressed as an int number with a L or a Lx suffix, where x is an integer between 2 and 16 (inclusive), representing the base of the number (used for parsing and printing only). Examples, 1 I1 = 123 2 I2 = 0xabc 3 4 F1 = 456.7F 5 F2 = 123e4F 6 7 D1 = 123D 8 D2 = 456.7 9 D2 = 456.7D 10 D3 = 123E4 11 D3 = 123E4D 12 13 C1 = 123C 14 C2 = 456.6C 15 16 L1 = 123456789L 17 L2 = 10001001110L2 18 L3 = 0x123abc456L16 These types support most of the common operators that are meaningful for them. For example, all the basic arithmetic operators such as: + (addition, unary plus), - (subtraction, unary minus), * (multiplication), / (division), % (modulo) and ** (power) are supported. 1 I1 = 123 + 456 2 I2 = 789 % 123 3 F1 = 123.5 ** 3 4 D1 = 789.5D / 123 5 L1 = 123456789L ** 123L Please see dao.type.int, dao.type.float, dao.type.double, dao.type.complex and dao.type.long for more information. 0.2 Enum Symbols enum is a type hybriding C++ enum and Ruby symbol types to offer the advantages of both types. It can be used as enumerated constant in C++ or as symbol in Ruby. Enum types can be declared in the same way as C++ enum: 1 enum MyEnum 2 { 3 AA, 4 BB, 5 CC 6 } Then it can be used in the following way: 1 e1 = MyEnum::BB # with constant folding; 2 e2 = MyEnum.BB # without constant folding; 3 e3 : MyEnum = $BB # with auto conversion; All e1, e2 and e3 will be an enum value with integer value equal to 1 and string symbol equal to "BB". The last is equivalent to: 1 # Use enum type on the fly: 2 e3 : enum<AA,BB,CC> = $BB Enum values can be used in switch-case statements, which can be optimized into table lookup, if the enums are explicitly typed or can be inferred. For example, 1 switch( (any)e1 ){ 2 case MyEnum::AA : ... 3 case MyEnum::BB : ... 4 case MyEnum::CC : ... 5 } 6 7 switch( e1 ){ 8 case $AA : ... 9 case $BB : ... 10 case $CC : ... 11 } Both will be optimized into table lookup, because the case values have well defined types (the cases in the second example have types inferred from the expression inside switch() ). 0.3 Strings In Dao, a string can be expressed as a sequence of characters enclosed by a pair of single qutotation marks or a pair of double quotation marks. The characters placed between the quotation marks must be formated according some rules (such as escaping quotation marks and other special characters and using numeric encodings of characters etc.). Please see dao.type.string for more information. 1 mbs = 'str' 2 wcs = "道语言" 3 mbs2 = 'It\'s green' 4 wcs2 = "\u9053\u8bed\u8a00" # the same as wcs: "道语言"; To use strings as it is written without special treatment of the characters, they can be expressed as verbatim string, which are quoted with a pair of identical compound marks in the forms of @[] and @@[]. Any number of letters, digits, underscores, blank spaces, dots, colons, dashes and assignment marks can be placed in between the squared brackets to make sure the marks will not appear inside the string. The difference between using @[] and @@[] is the same as the difference between using single quotation marks and double quotation marks. Please see dao.type.string for more information. 1 # C++ codes in MBS: 2 cpp = 3 @[cpp x] 4 class AA 5 { 6 int index; 7 }; 8 struct BB{}; 9 @[cpp x] 10 11 12 # Lua codes in WCS: 13 lua = 14 @@[lua] 15 local a = 1; 16 function Test() 17 io.write( 'Hello' ) 18 end 19 @@[lua] The content of a string can be accessed or altered using sub-indexing or slicing: 1 str = 'ABCDEFGHIJK'; 2 3 io.writeln( str[1] ) # the second character; 4 io.writeln( str[:4] ) # the substring from the start to the 4th character; 5 io.writeln( str[6:] ) # the substring from the 6th character to the end; 6 io.writeln( str[3:8] ) # the substring from the 3rd to the 8th character; 7 8 # Set single character: 9 str[1] = 'X'; 10 str[1] = 'X'[0]; 11 12 # Set a substring: 13 str[2:5] = '1234' # str = 'AB1234GHIJK' 14 str[2:5] = '123456' # str = 'AB123456GHIJK' 15 str[2:5] = '12' # str = 'AB12GHIJK' 16 17 # Using negative index: 18 io.writeln( str[-1] ) # the last character; 19 io.writeln( str[-2] ) # the second last character; 20 io.writeln( str[-2:] ) # the last two characters; String can be concaternated using + or +=, 1 str = 'ABCDEFGHIJK'; 2 3 str2 = str + '123' # str2 = ABCDEFGHIJK123 4 5 # Append a string: 6 str += '123' # str = ABCDEFGHIJK123 7 8 # Append a character: 9 str += 88 # str = ABCDEFGHIJK123X 0.4 Arrays Dao has built-in support for multi-dimensional numeric arrays. Such arrays can be defined by using the squared brackets [] or array{}. Using such constructs, one can either enumerate all the elements as a vector/matrix, or specify an arithmetic progression with a start value, a step value and the number of steps. If the step value is omitted, it will be assumed to be zero. 1 vec1 = [1, 2, 3] # array<int> vector, or 1x3 matrix; 2 vec2 = [1.0; 2; 3] # array<float> 3x1 matrix, or transposed vector; 3 mat1 = [1D, 2; 3, 4] # array<double> 2x2 matrix; 4 mat2 = [ [1, 2], [3, 4] ] # 2x2 matrix 5 mat3 = [ [1, 2, 3] : 5 ] # 5x3 matrix; 6 mat4 = array{ 1, 2; 3, 4 } # 2x2 matrix Like string, array support sub-indexing, slicing and negative indices: 1 mat = [ 1, 2, 3; 4, 5, 6; 7, 8, 9 ]; # 3x3 matrix; 2 3 rowvec = mat[1,:] # the second row; 4 colvec = mat[:,1] # the second column; 5 6 submat1 = mat[:1,:] # the first two rows; 7 submat2 = mat[:,1:] # the last two columns; 8 submat3 = mat[:1,1:] # intersection between the first two rows and the last two columns; 9 10 mat[0,:] = [11, 22, 33] # set the first row to [11, 22, 33]; 11 mat[:,1] += [11, 22, 33] # add [11, 22, 33] to the second column; 12 mat[:,1] += 100 # add 100 to the second column; 13 14 mat[:1,1:] += [10, 20; 30, 40] # add [10, 20; 30, 40] to sub-matrix of mat; Please see dao.type.array for more information. 0.5 Lists List can be created in similar ways as array, by enumerating elements or specifying an arithmetic progression, but using {} or list{} instead of [] or array{}. 1 list1 = { 1, 2, 3 } # list<int> 2 list2 = { 1.0, 2, 3 } # list<float> 3 list3 = { 1 : 2 : 5 } # list<int> 4 5 list4 = { 'abc', 'def' } # list<string> 6 list5 = { 123, 'abc' } # list<any> 7 8 list6 = list{ 'a' : 3 } # { 'a', 'a', 'a' } 9 list7 = { 'a' : 'b' : 3 } # { 'a', 'ab', 'abb' } List also supports sub-indexing, slicing and negative indices: 1 alist = { 0, 1, 2, 3, 4, 5 } 2 3 item = alist[1] 4 item = alist[-2] 5 6 sublist = alist[2:4] 7 8 alist[3] = 10 9 alist[4] += 10 0.6 Maps and Hash Maps A map or hash map organizes a set of key/value pairs into a structure for efficient lookup. The keys in a map are ordered, while the keys in a hash map are unordered. A map can be created using {key=>value...} or map{key=>value...}. Replacing the => with colon -> will create hash maps. Map and hash map can be used in identical ways. 1 amap = { 'abc' => 123, 'def' => 456 } 2 ahash = { 'abc' -> 123, 'def' -> 456 } 3 4 amap = map{ 'abc' => 123, 'def' => 456 } 5 ahash = map{ 'abc' -> 123, 'def' -> 456 } Sub-scripting and slicing are also supported for map to access value(s) through key(s). 1 amap = { 'abc' => 123, 'def' => 456, 'ghi' => 789 } 2 3 value = amap[ 'abc' ]; 4 submap = amap[ 'abc' : 'def' ]; 0.7 Tuples Tuple is a very handy type, which can be used to hold a fixed number of items, with type information recorded for each of them. In a tuple, each item can have a name, which can be used to access the item as field. They can be created in similar ways as creating lists and maps, but use () instead. 1 tup1 = ( 123, 'abc' ) # tuple with unnamed items; 2 tup2 = ( index => 123, 'abc' ) # the first item is named as "index"; 3 tup3 = tuple{ 123, name => 'abc' } # the second item is named as "name"; Each item of a tuple can be accessed using its index or field (item name). New tuples can be created from other tuples by slicing. 1 tup = ( index => 123, 'abc', [1,2,3] ) 2 3 id = tup[0] 4 id = tup.index 5 tup.index = 456 6 7 tup2 = tup[:1] # ( index => 123, 'abc' )