WebSiphon 2 Guide: SiphonScript Data Types
contents prev next

Data Types

Variables in SiphonScript are very loosely typed. This means there is little distinction between different types of data, and you do not need to declare variables as a particular type.

The table below lists the different data types that SiphonScript recognizes, with some examples of what possible values look like. Variables are automatically coerced to the most appropriate type whenever they are used. The coercion table at the end of this section illustrates how data is coerced between different data types.

Data Type Example
Nullnull
Booleantrue
 false
Integer1073
 42
Float6.432
 0.005
String"Hello world!"
 "Lillith"
List[1 2 "a" "b"]
 [["a" 1] ["b" 2] ["c" 3]]

NULL The null data type is used to represent a non-existant or invalid value. There is no printable equivalent to null, nor is it equal to zero, it is simply the absence of any value.

BOOLEANS A boolean is actually an integer, where a value of 0 is false and any other value is true. Thus, any expression that returns an integer or can be coerced into an integer may be used as a boolean. In a script, you may use the keywords true and false as an alternative to 1 and 0, respectively.

INTEGERS An integer is a whole number without a decimal point. The number may be positive or negative, but is always a whole number.

FLOATS A float is a number with a decimal point. The number may be positive or negative and is a greater level of precision than an integer. A float in SiphonScript has 8 bytes of precision and is basically the same as a "double" in C or C++. (For those who truly care, a SiphonScript float is an IEEE 64-bit double precision floating point value.)

STRINGS A characters string can represent any text value. They begin and end with double quotes, and there is no set limit to their length except available memory. Non-printable characters such as carriage returns or tabs may be put into a string using special escape codes as in the table below. A backslash followed by any character not listed in the table below will result in that same character.

Escape CodeASCII ValueCharacter
\t009tab
\v011vertical tab
\r013carriage return
\n010linefeed (newline)
\f012form feed
\b008backspace
\"034"
\\092\

BINARIES A binary can hold various different types of data, such as images and resources. There is no printable equivalent to most binaries.

LISTS A list is special data type in SiphonScript, that may contain any amount of information as a dynamic array. Lists can contain any type of items, including expressions, function calls, or even sub-lists. A list begins with "[" and ends with "]", and individual items are separated by either a space or comma.

List Accessors
To work with individual items in a list use item accessors. The examples below demonstrate the different methods used to access list items.

Examples:

  1. my_list = [1 "a" 2 "b" 3];
    	print my_list'1;
    	>> 1
  2. print my_list'4;
    	>> b
  3. print item 2 of my_list;
    	>> a
  4. print itemAt(my_list, 5);
    	>> 3

List accessors are discussed more in the Expressions and Operators chapter.

Potential Pitfall: Ambiguous Lists
There are certain instances where a list that looks correct may have multiple meanings and therefore confuses the compiler. A segment of script that has multiple possible meanings is considered ambiguous and may need to be rewritten using parenthesis or commas to separate list items explicitly.

my_list = [1 2 -3];

For example, the above list is ambiguous and must be rewritten to be properly understood. When the SiphonScript compiler is reading the above statement, it will actually see only two items even though it appears there are three distinct items in the list. What the compiler sees is a first item whose value is 1, and a second item whose value is 2 minus 3 (which evaluates to -1). Each of the two assignment statements below demonstrate two methods of explicity performing the intended task.

// Explicit list assignment using...
my_list = [1 2 (-3)];     // ...parenthesis
my_list = [1, 2, -3];     // ...commas

Another ambiguious list may be caused by using a variable as a list item followed by an expression in parenthesis. The script segment below demonstrates the ambiguous assignment statement which causes the compiler to think there is a single list item: a call to the function named "my_var". Below the incorrect statement are several methods of rewriting the list assignment explicity.

// Watch Out! Ambiguous!
my_list = [my_var (1 + 2)];

// Some explicit alternatives...
my_list = [(my_var) (1 + 2)];
my_list = [my_var, (1 + 2)];
my_list = [my_var 1+2];

Understanding How Lists Work
WebSiphon includes an entire library of functions that may be utilized to perform many different manipulations on lists which introduce a great deal of functionality in your scripts.

Many of the list functions work directly on the list passed to them rather than working with a copy of the list. The reason for this is purely speed in working with large lists, which would suffer greatly if a new copy of a list were required for each operation performed. So, what does that mean to you, the future SiphonScript wizard? Keep in mind that if you wish to make an exact copy of a list and work with its contents rather than modifying the contents of the original list you must use the deepCopy() function. When referencing the list functions library you should assume that all functions work with the list directly rather than with a copy unless the function descriptions specifically states otherwise.

The example below demonstrates a common mistake made by users new to the SiphonScript language when working with lists:

my_list = [1 2 3 4 5];

temp_list = my_list;
temp_list'3 = 42;

descending = true;
temp_list = sort(temp_list, descending);

printList(temp_list);
printList(my_list);

>> [42 5 4 2 1]
   [42 5 4 2 1]

In the above example, the problem occurs when the variable temp_list is assigned the value of my_list. What this actually does is point both variables to the same list data, so any changes made to either variable will affect the same list which causes the unexpected results shown above. The modified script shown below would produce the expected results

my_list = [1 2 3 4 5];

temp_list = deepCopy(my_list);
temp_list'3 = 42;

descending = true;
temp_list = sort(temp_list, descending);

printList(temp_list);
printList(my_list);

>> [42 5 4 2 1]
   [1 2 3 4 5]

Associative Lists
An associative list is a standard list organized in a structured fashion allowing it to be used to reference values by name, as in a dictionary. An associative list must be in the format [[<name1> <name2> <name3>] [<value1> <value2> <value3>]]. However, using the built-in associative list functions is the easiest path to follow so you need not construct the list manually.

Further documentation and examples of using associative lists is provided in the function reference. The following functions are used in the creation and manipulation of associative lists:

  1. assocAt
  2. assocPut
  3. assocTake

Assigning Values to List Items
It should be noted that SiphonScript does not let you assign a value directly to an element of a list sub-list using list accessors. You can modify the value of a primary list element, but not one in a sub-list (attempting to assign a value to a sub-list will result in a Syntax Error). Example:

my_list = ["Hi" ["What's Up", "Not Much"]];

my_list'1 = "Hello"; // this will work
my_list'2'1 = "Yo"; // but this will not work - Syntax Error

To accomplish the above, you need to use the workaround:

my_list = ["Hi" ["What's Up", "Not Much"]];
templist = my_list'2;
templist'1 = uppercase (my_list'2'1);
printList(my_list);
>> [ "Hello", [ "WHAT'S UP", "Not Much" ] ]

At this point my_list'2'1 (which is exactly the same as templist'2) will be updated as you intended.

Coercion

SiphonScript is a very loosely typed language, so variables are coerced between multiple types quite often throughout the execution of a script. The general rule for any operation is that, given two different data types, both of which are acceptable, the result will be of the type with the highest precision (i.e. floating point as opposed to an integer).

The table below outlines how variables are coerced from one type to another:

Coercion ExamplesNotes
Integer to Float 12 -> 12.0  
Float to Integer 900.1 -> 900
-57.64 -> -57
Decimals are dropped, not rounded
Integer to String 12 -> "12"  
Float to String 9.01 -> "9.01"
12.000 -> "12"
If there are no non-zero values following the decimal point, decimal values will be dropped
String to Integer "50" -> 50
"5.76" -> 5
"nada" -> null
If a numeric value is not found in the string, null will be returned
String to Float "50" -> 50.0
"5.76" -> 5.76
"nada" -> null
If a numeric value is not found in the string, null will be returned
Anything to List 50 -> [50]
"nada" -> ["nada"]
 
List to String [1 2 3] -> "1 2 3"
[1 [2 3]] -> "1 2 3"
Lists are flattened when coerced to a string.
List to Integer [1 2 3] -> null  
List to Float [1 2 3] -> null  

To coerce a variable from one type to another, the coerceTo() function should be used. Keep in mind that coercion of variables is somewhat different from simply formatting output with the as operator. The as operator will always create a string, even though the value of that string may appear to have changed types.

contents prev next

Copyright (c)1996-2003 Purity Software