Variables and Data types All about the KVS variable and datatype management |
Basic syntax |
A variable identifier is composed by a '%' (percent) sign followed by a sequence of letters, digits or underscores. Examples of valid variable names are: |
%i %variable %MyVar %1 %thisisavar %2ndName %_hidden |
Variables are created when you assign something to them: there is no need for a declaration (unlike other languages such as C/C++, Java or VB). |
# create a variable named %X by assigning the value 10 to it %X = 10 # use the variable echo "The value of X is" %X |
Local and global variables |
Variables can be local or global. Local variables preserve their contents only inside the scope of a single script. Global variables are shared between all the scripts and preserve their contents until they are explicitly unset or until KVIrc quits. Local variables start with a lowercase letter while the global ones with an uppercase letter. |
%var = 10; # this is a local variable %Var = 10; # this is a global variable |
You can also force a variable that start with a lowercase letter to be global by pre-declaring it with the global keyword. |
# copy this script to a file and run /parse <filename> global %a %a = "The contents of the variable a" %b = "The contents of the variable b" # %a is a global variable now : all the other scripts can see its value # %b is a local variable and no other scripts can see its value |
If you have executed the example above from a file (by the means of parse) then now you can type |
echo %a |
in the commandline to see the contents of the variable %a. If you also try |
echo %b |
you will see nothing printed since %b was local to the parsed script. |
Data types |
KVS has three main categories of data types: scalars, arrays and associative arrays (also known as dictionaries or hashes). |
Scalars |
The scalars are simple variables containing a single value (a string or an integer). |
# %a is a scalar variable %a = "This is a string" echo %a %a = 24.5 echo %a |
Arrays |
Arrays are collections of items indexed by integers. The array items are selected by placing the index in square brackets just after the array name. |
%arrayName[index] |
An easy way to create an array is to use the $array function. |
%a = $array("element1","element2","element3"); # Create an array with 3 items for(%i=0;%i<3;%i++) { echo %a[%i]; # Accessing the %i'th element of the array } |
Note that in the example above %a refers to the whole array while %a[%i] refers to one of its elements, in particular the one with index %i. You also create an array by explicitly assigning to one of its elements: |
%a[9] = "This is an array element"; |
Array indexes are zero-based so in the example above you have created an array with 10 items. You can find out an array's length with the $length() function. |
%a[9] = "This is an array element"; echo $length(%a) |
Be aware that by making such an assignment you implicitly consume some memory for all the preceding array items (even if they are unset). This means that a simple instruction like the following may eat a huge amount of memory at once: |
%a[1000000] = "An array element faaaaaar away..."; echo $length(%a) |
Food for thought: |
KVIrc allocates a pointer for each item in the array. The pointer is empty when the item is unset and points to an additional block of memory when the item is set. The size of a pointer is platform dependent: on the platforms supported by KVIrc it's either 32 or 64-bit. The size of the additional block depends both on the platform and on the contents of the item... it's average value may be around 16 bytes. The array size is determined by the last SET element index. All this this means that in the worst case (64 bit assumption) an array in that the highest indexed item set is N eats up at least N*8+16 bytes of memory. |
Besides the traditional indexed looping method you can also use the foreach command to iterate the items of an array. Be aware that foreach will not iterate over unset items in the array unless you use the -a switch. |
%Array[0]=Pippo %Array[1]=Pluto %Array[2]=Paperino %Array[5]=Prova foreach(%item,%Array)echo Got Item: %item |
Note that the items 3 and 4 are simply skipped. |
Hashes |
The hashes are collections of items indexed by strings: the word hash is in fact a shortcut for hashtable. In literature hashes are also called associative arrays, dictionaries or key-value pair sets. The hash items are selected by placing the key in curly brackets just after the hash name. |
%hashName{key} |
An easy way to create a hash is to use the $hash function. |
%a = $hash("key1","value1","key2","value2","key3","value3") foreach(%key,$keys(%a)) { echo "KEY:" %key "VALUE:" %a{%key}; } |
Note that in the example above %a refers to the whole hash while %a{%i} refers to one of its elements, in particular the one with the key %key. You also create a hash by explicitly assigning to one of its elements: |
%a{"MyKey"} = "MyValue" |
You may have already noticed that the $keys() function returns the array of the hash keys: it is useful to iterate over the hash items. |
Mutability of variables |
KVS is not strictly typed: any variable can assume different type identities at different times, even in the same script. |
# %a is a scalar %a = "This is a string" # %a becomes an array with 3 elements %a = $array("element1","element2","element3"); # %a becomes a hash with two values %a = $hash("key1","value1","key2","value2"); |
In literature this kind of variable is called variant and this is the term that you will find all around the documentation when an explicit data type is not requested. Note that array and hash items are variants too. This means that you can have arrays of arrays, hashes of arrays of hashes and any other multidimensional combination you like. However remember that hash keys are strings and not variants so you can't use an array as hash key. |
# here we eat 256 locations of memory at once :) %a[16][16] = 10 # a hash of hashes: here we eat just two memory locations %a{"16"}{"16"} = 10 |
In most cases the KVS engine manages automatically the conversion between data types. For example, when you put an array in a place where a scalar is requested, KVIrc automatically transforms it to a scalar string by joining all the items with a comma. |
%a = $array("element1","element2","element3"); echo %a; # echo expects its arguments to be scalar |
Conversely, when you put a scalar in place of an array, KVIrc automatically transforms it to an array with a single item. In this way a function like $sort works also with a scalar. In literature the conversions between data types are called casts. When the conversion is automatic the cast is said to be implicit. KVS handles also the other possible implicit casts: scalar->hash,hash->scalar,array->hash,hash->array. Experiment with it. |
More about scalars |
Internally KVS is implicitly typed: the scalar data type is in fact a set of types that KVIrc manages silently. The types are: integer, string, real, boolean and hobject. Integers are non-floating point numbers. Their allowable range depends on the underlying platform integer size: usually 32 or 64 bit. Reals are floating point numbers. Their allowable range and precision depends on the underlying platform. Booleans are either true or false values. For boolean constants, use $true or $false. Don't use true or false, because the engine sees them as non-empty strings, which always evaluate as true. hobject stands for Handle to Object and it is a sort of a C++ pointer. Detailed description of objects is in this document. Basically anything else fails in the string category. In most cases KVS manages all the conversions between data types automatically. For example an integer becomes a true boolean when it's non zero and a false boolean otherwise, a real becomes an integer by truncating it's fractional part... You can find out the type of a specified variable by using the $typeof() function. |
%a = 1 echo $typeof(%a) %a = 1.1 echo $typeof(%a) %a = $true echo $typeof(%a) %a = "test" echo $typeof(%a) |
There is also another subtle type of scalar called nothing. It stands for an empty (unset) variable. |
%a = $nothing echo $typeof(%a) |
Nothing is something in between a data type and a special value for all the other data types: it represents absence of information. This may look a bit confusing but realize that all the unreferenced KVS variable are in fact of type nothing: they just don't exist. This means that you can use $nothing() to effectively unset a variable. Again, when possible, the conversion between nothing and the other data types is performed automatically. Nothing becomes an empty string, a null object handle or an empty array. |
Explicit casts |
You can make explicit conversions between some data types by using the casting functions. $integer() will attempt to convert the variant parameter to an integer, $real() will cast to a floating point value, $boolean() will convert to a true/false value, $string() will explicitly convert to a string, $array() will convert to an array and $hash will return a dictionary. By assigning the special $nothing() value you will convert to the nothing data type (or simply unset the variable). The only explicit conversion that is not possible is to hobject. As stated several times in this document, KVS tries to manage the casts automatically so you usually don't need to care about it. The explicit casts are provided for the very few cases where an automatic conversion would lead to an unexpected value (for your script) and for writer's clarity. |
More about variables life-cycle |
As stated above variables start their existence when you assign something to them. After a variable has been created it persists until it goes out of his scope (remember about local and global variables?) or you explicitly destroy it. You will usually not care about it and just leave the KVS engine to do his cleaning job but it's still worth knowing that you actually can force KVIrc to free the memory used by a variable. The first method to explicitly destroy a variable is to call unset on it. unset in fact accepts a list of variables so you can destroy more variables at once. |
%a = $array("data","for","a","really","huge","array","of","items") %b = 10 %c = "just a string that eats memory" unset %a,%b,%c |
The KVS engine treats unset variables just like empty strings. The opposite is also valid: empty strings behave like empty (unset) variables. This means that you can assign an empty string to a variable to unset it. |
%a = "test"; # %a starts his existence %b = "test2"; %a = ""; # %a is in fact unset %b = ; # syntactically this is just the same as above |
Note that because of mutability of variables (explained above) you can use the empty string assignment also to free arrays and hashes. |
Extended scope variables |
Beside local and global variables there is a third family of them. Variables that have a ':' character just after the leading '%' are extended scope variables. %:index, %:Hello, %:something.else are all valid special scope variable names. They're actually used in popups and in timers (but later I might find other usages as well :). "Extended scope" means that these variables are somewhere in the middle between global and local variables. They normally act as local, but in some cases their lifetime and visibility may be extended. For example, in the popups, all the special scope variables are visible during all the "lifetime" of a popup (so from the prologue code call to the moment when the user selects an item and the corresponding code is executed). This allows you to pre-calculate some data or conditions in the popup prologue and use this data in the popup item conditions and item handlers. |
Variable evaluation |
A variable can appear in every place where a parameter is expected: so after the command name, after a switch or inside an identifier parameters. The KVS parser will try to extract the longest possible variable name after a literal percent '%' sign everywhere in the parameter string. So the command sequence |
%number = 1st; echo this is my %number variable test |
will first assign 1st to the variable %number and then execute "echo this is my 1st variable test". The following example will not work as expected. |
%number = 1; echo this is my %numberst variable test |
KVS will assign 1 to %number in this case but the next variable name extracted will be %numberst that is actually empty; so finally "echo this is my variable test" will be executed. To avoid this problem you can use the backslash escape character: |
%number = 1; echo this is my %number\st variable test |
Putting it all together |
Variables can be either local, global or have an extended scope. Their start to exist when you first assign something to them and they disappear when they go out of their scope or you explicitly destroy them. KVS has 8 builtin data types: string, integer, real, boolean, hobject, nothing, array and hash. The first 6 are scalar data types while the last two are not. When possible, KVS manages all the conversions between data types silently. In the few cases in that an implicit conversion is not possible you have to manage the conversion manually otherwise KVS will complain. |