load help; @[name] dao.data @[name] @[title] Constants, Variables and Invariables @[title] @[text] Dao supports the explicit declaration of constants, local variables, static variables, global variables and invariables. @[table] ##Keyeord ##In Top Scope ##In Local Scope ##In Class Body ##const &&Global Constant &&Local Constant &&Class Constant ##var &&Global Variable &&Local Variable &&Class Instance Variable ##invar &&Global Invariable &&Local Invariable &&Class Instance Invariable ##static &&Static Variable &&Static Variable &&Class Static Variable @[table] @[text] @[name] dao.data.const @[name] @[title] Constants @[title] @[text] Constants are declared with keyword @[green]const@[green], @[code] const DEFAULT_INDEX = 123 const DEFAULT_NAME = "abc" @[code] Constants can only be initialized with constant expression. Constants that are declared at the top lexical scope are global constants. And constants declared in nested scopes are local constants: @[code] const konst = "global constant" for(var i = 1 : 5 ) { const konst = 123 if( i > 3 ) { const konst = "local constant" io.writeln( konst ) # Output: local constant } io.writeln( konst ) # Output: 123 } io.writeln( konst ) # Output: global constant @[code] Inside class body, @[green]const@[green] can be used to declare class wise constants, which are stored in the class objects instead of the instance objects. They can be accessed with the class objects. @[code] class Klass { const name = "Klass" } io.writeln( Klass.name ) @[code] @[text] @[name] dao.data.var @[name] @[title] Variables @[title] @[text] Keyword @[green]var@[green] can be used to declare local and global variables. @[code] var current_index = 456 # global variable; var current_name = "def" # global variable; @[code] Variables can be initialized with any expressions. If used at the top lexical scope, it will declare global variables, otherwise the declared variables will be local. @[code] var variable = "global variable" for(var i = 1 : 5 ) { var variable = 123 if( i > 3 ) { var variable = "local variable" io.writeln( variable ) # Output: local variable } io.writeln( variable ) # Output: 123 } io.writeln( variable ) # Output: global variable @[code] Inside class body, @[green]var@[green] can be used to declare class instance variables, which are stored in the class instance objects. They can only be accessed with class instance objects. @[code] class Klass { const name = "Klass" var value = 123 } io.writeln( Klass.value ) # Error! var klass = Klass() io.writeln( klass.value ) # OK! @[code] @[text] @[name] dao.data.invar @[name] @[title] Invariables @[title] @[text] In every places where @[green]var@[green] can be used, @[green]invar@[green] can be used as well, to declare local, global or member invariables. @[code] invar invariable = "global invariable" for(var i = 1 : 5 ) { invar invariable = 123 if( i > 3 ) { invar invariable = "local invariable" io.writeln( invariable ) # Output: local invariable } io.writeln( invariable ) # Output: 123 } io.writeln( invariable ) # Output: global invariable @[code] Very much like constants, invariables cannot be modified once initialized. But unlike constants which must be initialized with constant expressions, invariables can be initialized with ordinary variables or expressions. Though the values of invariables cannot be modified through the invariables themselves, they can still be modified through the original variables. @[code] var varlist = { 123 } invar invlist = varlist varlist.append( 456 ) # OK! Now, invlist = { 123, 456 } invlist.append( 456 ) # Error! @[code] Additionally @[green]invar@[green] can be used in parameter list to declare invariable parameters. @[code] routine Rout( invar abc = 123 ) { abc += 1 # Error! } @[code] Though invariables cannot be modified, they do can be reinitialized at their declaration sites. For example, @[code] for(var i = 1 : 3 ){ invar index = i # OK! index += i # Error! } @[code] But for class instance invariables, they can be initialized anywhere inside the class constructors. @[code] class Klass { invar mapping = {=>} routine Klass( name: string, value: int ) { mapping = { name => value } # OK! } routine Method() { mapping = { "abc" => 123 } # Error! mapping[ "abc" ] = 123 # Error! } } @[code] @[green]invar@[green] can also be used to declare class methods that do not modify their instance variables. @[code] class Klass { var value = 123 routine Modify() { value += 456 } invar routine Method() { Modify() # Error! value += 456 # Error! return value + 456 } } @[code] @[text] @[name] dao.data.static @[name] @[title] Static Variables @[title] @[text] Another type of variable is the static variable which can be declared with the @[green]static@[green] keyword. Static variables must be initialized with constant expressions. @[code] static stat = "static variable" for(var i = 1 : 5 ) { static stat = 123 if( i > 3 ) { static stat = "local static variable" static nested = [1,2,3] io.writeln( stat ) # Output: local static variable } io.writeln( stat ) # Output: 123 io.writeln( nested ) # Error! "nested" not visible here. } io.writeln( stat ) # Output: static variable static abc = rand(100) # Error! Expecting constant expression. @[code] Outside class body, a static variable is a global variable with strictly local visibility within its declaration scope. So if a routine with static variables is executed multiple times, all the executions will access the same static variables. @[code] routine Test() { static aux = 0 aux += 1 io.writeln( aux ) } Test() # Output: 1 Test() # Output: 2 Test() # Output: 3 @[code] Similarly, static variables in class are variables shared across different class instances, as they are stored in the class objects instead of the instance objects. They can be accessed with the class objects. @[code] class Klass { static state = [1,2,3] } io.writeln( Klass.state ) @[code] @[text]