3. Data types and literals

HSL has multiple data types; strings, numbers, arrays (which also works as an ordered map to store key-value pairs, similar to PHP’s array), objects (created by classes) and functions (both anonymous functions and named function pointers). Some of these data types may be represented as literals. There is also a none (or null) data type that is rarely encountered (e.g. a return statement without a value or a failed json_decode() both of which return none).

3.1. String

There are two kinds of string literals, double-quoted strings and raw strings. Double-quoted strings support language features such as variable interpolation and escape sequences. Most functions (e.g. strlen() and substr()) are not UTF-8 aware, with the exception of regular expression matching (e.g. pcre_match()) which may be configured to be UTF-8 aware with the /u modifier.

3.1.1. Double-quoted string

Variable interpolation replaces $variable placeholders within string literals. Variables are matched in strings with the following pattern $[a-zA-Z]+[a-zA-Z0-9]. If needed there is also a more explicit syntax ${variable} (which allows variables mid-words). Interpolating an undeclared variable raises a runtime error.

Escape sequence Meaning
\\ Backslash (\)
\" Double quote (")
\$ Dollar sign ($)
\n ASCII Linefeed (LF)
\r ASCII Carriage Return (CR)
\t ASCII Horizontal Tab (TAB)
\xhh Character with hex value hh

3.1.2. Raw string

Raw strings do not support variable interpolation nor escape sequences. This make them suitable for regular expressions. Raw strings start and ends with two single quotes on each side '', with an optional delimiter in between. The delimiter can be any of [\x21-\x26\x28-\x7e]*; simply put any word.

''raw string''
'#'raw string'#'


There is no performance difference between double-quoted and raw strings containing the same value. However if special characters needs to be escaped then raw string are recommended for clarity.

3.2. Number

The number type is a double-precision 64-bit IEEE 754 value. If converted to a string it will be presented in the most accurate way possible without trailing decimal zeros.

echo 1.0; // 1


After some arithmetic operations on floating point numbers; the equality (==) of two floating point numbers may not be true even if they mathematically “should”. This caveat is not unique to HSL, instead it is the result of how computers calculates and stores floating point numbers. Arithmetic operations on numbers without decimals are not affected.

3.2.1. Hexadecimal

Numbers may be entrered as in hexadecimal form (also known as base 16) using the 0x prefix; followed by [0-9a-f]+.

echo 0xfa; // 250

3.2.2. Octal

Numbers may be entrered in octal form (also known as base 8) using the 0o prefix; followed by [0-7]+.

echo 0o372; // 250

3.2.3. Binary

Numbers may be entrered in binary form (also known as base 2) using the 0b prefix; followed by [0-1]+.

echo 0b11111010; // 250

3.2.4. Boolean

The keywords true and false are aliases for 1 and 0.


Boolean true and false should not be used to test for truthiness e.g. in if statements. if statements checks for values which are not false, which isn’t the same as numeric 1 (true).

if (5 == true) { } // false: 5 is not equal to 1
if (5) { } // true: 5 is not false, hence true

3.3. Array

An array is a very useful container; it can act as an indexed array (automatically indexed at zero, or the highest current index + 1) or as an ordered map (associative array) with any and mixed data types as key and value. The short array syntax for literal arrays [] is recommended.

// indexed arrays
echo array("value", "value2");
echo ["value", "value2"];
echo [0 => "value", 1 => "value2"];

// associative arrays
echo array("key" => "value");
echo ["key" => "value"];

// multidimensional arrays
echo ["key" => ["key" => "value"]];

// automatic indexing
echo ["foo", 3=>"bar", "baz"]; // 0=>foo, 3=>bar, 4=>baz


Accessing any element in a zero indexed array using the subscript or slice operator is very fast (it has the complexity of O(1)).

3.4. Function

Both anonymous functions (closures) and named function pointers (references to functions) are available. This datatype is primarly used to be passed as callbacks to other functions.

3.4.1. Anonymous functions

An anonymous function is a unnamed function, it can be passed as value to a function or assigned to a variable. An anonymous function can also act as a closure. The global variable scoping rules apply.

$multiply = function ($x, $y) { return $x * $y };
echo $multiply(3, 5); // 15

3.4.2. Named function pointers

A named function pointer is a reference to a named function. It can reference both a builtin function or a user-defined function. Prepending the function name with the builtin keyword works as expected.

function strlen($str) { return 42; }

$function = strlen;
echo $function("Hello"); // 42

$function = builtin strlen;
echo $function("Hello"); // 5

3.5. Object

An object is an instance type of a class statement or of a builtin class (such as Socket or File).

3.6. None

This data type is represeneted by the keyword none. It may be used to indicate error-result or no return value from functions such as. json_decode() (in case of a decode error) or from a user-defined function with no or an empty return statement. This data type should not be used as an argument to other built-in functions as it yields undefined behavior for the most part. The only functions safe to handle this data type is:

$obj = json_decode("...");
if ($obj == none)
        echo "None";