Version: v0.6.0 - Beta.  We welcome contributors & feedback.  THanks!

Intermediate Features

Summary 

These features are suitable for programmers that already have some programming experience.

They are not necessary in most THT programs.

Optional Argument Parens 

Functions that take zero arguments can leave out the empty parentheses.

// With empty arguments
function doSomething() {
    // ...
}

// Same, without parentheses
function doSomething {
   // ...
}

// Either way, functions are always called with parens.
doSomething();

Keyword Shortcuts 

The following one-letter shortcuts can be used instead of the full keyword.

F = function
T = template

These shortcuts reduce repetition, helping you focus more on the “shape” of your code — i.e. the identifiers that are unique to your program.

Example:

F addNumbers {
    return 1 + 2 + 3;
}

T resultHtml(name) {
    <h1>> Hello {{ name }}!
}

ImportantYour variable and function names should still be clear and descriptive! These are simply shortcuts for keywords that are extremely common.

Quoted (Quick) Lists 

A list prefixed with q will automatically convert the contents to a list of strings. The tokens are separated by whitespace (spaces or newlines).

$colors = q[red blue green];
// Same as ['red', 'blue', 'green']

// or separated by newlines
$colors = q[
    red
    blue
    green
];

One-Liners 

When you have a block with a single statement, you can use a colon : to place it on the same line without curly braces.

if $a == 1: print('One!');

// Same as...
if $a == 1 {
    print('One!');
}

// Example function
F addOne($n): return $n + 1;

// Example foreach
foreach $colors as $c: print($c);

// Example nested (try not to overdo it)
foreach $nums as $n: if $n < 10: print($n);

Operators 

Ternary ? :

The ternary operator is a shortcut for 'if a, then b, else c'.

It is used as an expression to determine a value.

// If/else form
if condition {
    $a = $result1;
} else {
    $a = $result2;
}

// Ternary form
$a = condition ? $result1 : $result2;

// Examples
$a = true ? 'Yes' : 'No';   //= 'Yes'
$b = false ? 'Yes' : 'No';  //= 'No'

$badge = $isVerified ? '(Verified User)' : '';

OR Assign ||=, AND Assign &&=

Logic and assignment can be combined into a single operator.

// OR assign.  Useful for assigning a default value.
$numGuests ||= 1;

// same as...
if !$numGuests: $numGuests = 1;

// AND assign.  Useful for processing a value further.
$date &&= formatDate($date);

// same as...
if $date: $date = formatDate($date);

OR Value ||:, AND Value &&:

Instead of evaluating true/false, logical value operators return the value of either side.

JargonThis is similar to “Null Coalescing” operators in other languages.

// OR value.
// Useful for assigning a default value.
$id = $user.id ||: -1;

// same as...
if $user.id {
    $id = $user.id;
} else {
    $id = -1;
}

// AND value.
// Useful for checking if an object is valid.
$id = $user &&: $user.id;

// same as...
if $user {
    $id = $user.id;
} else {
    $id = $user; // falsey value
}

Splat ...

The ... prefix operator can be used to pack and unpack function arguments to/from Lists.

// Combine remainder arguments into a single List.
F doSomething($first, ...$rest) {
    print(rest);
}

doSomething(0, 1, 2, 3);
//= [1, 2, 3]
F add($first, $second, $third) {
    print($first + $second + $third);
}

// Expand a List into multiple arguments
$args = [11, 22, 33];
add(...$args);
//= 66

Bitwise Operators

Because bitwise operations are rarely used in web development, THT uses non-standard operators (borrowed from Perl 6) to avoid accidental confusion with their Logical counterparts (e.g. & vs. &&).

+|  bitwise OR
+&  bitwise AND
+^  bitwise XOR
+~  bitwise NOT
+>  bitwise SHIFT RIGHT
+<  bitwise SHIFT LEFT

These can be used with literal binary digits with the 0b prefix.

Example:

$bin = 0b100 +& 0b110;
//= 4 (0b100)

Spaceship <=>

The spaceship operator compares two numbers and returns -1, 0, or 1, depending if the 1st number is less than, equal, or greater than the 2nd number.

This is primarily used for sorting functions.

1 <=> 2  //= -1
1 <=> 1  //=  0
2 <=> 1  //=  1

$letters = q[x y z];
$letters.sort(F ($a, $b) { return $b <=> $a });

//= ['z', 'y', 'x']

Cat ^^

The cat ^^ prefix operator applies advanced opti-meow-zation to a variable.

$moneyInBank = 30001.67;
print(^^$moneyInBank);
//= 'MEOW'

Regular Expressions 

Some string methods take a regular expression (aka “regex”) string as an argument.

Regex strings are prefixed with a lowercase 'r'. (e.g. r'[a-z]+').

Compared to normal strings, backslashes are treated literally.

See Regex.

'123 street'.match(r'[a-z]+');
//= ['street']

'abc'.match(r'\d+');
//= false

// case insensitive match
'Hi, Theo'.match(r'theo'.flags('i'));
// ['Theo']

Anonymous Functions 

You can assign a standalone function directly to a variable. This allows it to be passed into other functions, enabling functional-style programming.

$fnDouble = F ($num) { return $num * 2 };
$fnDouble(8);
//= 16

$numbers = [1, 2, 3];
$numbers.map($fnDouble);
//= [2, 4, 6]

Closures

A closure is a type of anonymous function that keeps a local variable in scope when the function is declared. The variable can then be accessed when the function is later called.

Use the keep keyword to retain a local variable.

F createLogger($messageType) {

    $fLog = F ($message) keep ($messageType) {
        print($messageType ~ ' -> ' ~ $message);
    };

    return $fLog;
}

$fLogUserEvent = createLogger('user');
$fLogUserEvent('logged in');
//= 'user -> logged in'

$fLogSystemEvent = createLogger('system');
$fLogSystemEvent('shut down');
//= 'system -> shut down'

Expression Functions

Use x{ ... } notation to create an anonymous function that automatically returns a single expression.

Expression functions automatically define arguments $a, $b, and $c if they are passed in as 1st, 2nd, 3rd arguments, respectively.

// Example: map function
[1, 2, 3].map(x{ $a * 10 });
//= [10, 20, 30]

// same as...
[1, 2, 3].map(F ($a) { return $a * 10 });


// Example: reverse sort
$users.sort(x{ $b <=> $a });

// same as...
$users.sort(F ($a, $b) { return $b <=> $a });

JargonThis feature is usually referred to as a “Lambda” in other languages.

Argument Typing 

You can declare the type of each argument in a function. Calls that don’t match these types will fail at runtime.

To declare a type, append a type token to the argument with a colon :.

Types are strictly enforced. They are not coerced, except an integer may be given to a function expecting a float.

// Take an integer and a string
F countItems($num:i, $itemName:s) {
    print('You have ' ~ $num ~ ' ' ~ $itemName);
}

countItems(3, 'apples');
//= 'You have 3 apples'

countItems('apples', 3);
// ✖ ERROR. Arguments are reversed.

Type Tokens

s   = string
b   = boolean
i   = integer
f   = float
l   = list
m   = map
o   = object
fn  = function
any = all types

The any type is the same as delaring no type at all. It is used to explicitly document that no type is enforced.

Try/Catch 

When something goes wrong, it’s usually best to let the program die. A dead script can’t do any more damage, and is less likely to become a security vulnerability.

However, sometimes you want to provide a fallback for specific errors.

An Exception is an error that can be trapped with try/catch. The catch block will only run if there is an Exception in the try block.

$content = '';
try {
    // Will throw an Exception if it can't read the file.
    $content = File.read('important.txt');
} catch $e {
    // Error. Try to restore it and continue.
    $content = getDefaultContent();
    File.write('important.txt', $content);
}

finally

A finally block can be used to define code that will run regardless of whether or not an Exception occurred.

This is optional, and is usually intended for cleanup logic that is invoked before the program ends.

try {
    // initial code
} catch $e {
    // run if an Exception happens
    print(e.message());
} finally {
    // always run this after the above blocks complete
}

TipThis is usually unnecessary, thanks to PHP's atomic request cycle. Each THT request is automatically cleaned up after it ends (e.g. closed file handles and database connections).

die

You can trigger an Exception manually with die.

if !fileExists {
    die('Important file not found.');
}

To halt the program without triggering an Exception, use System.exit().

Match 

In place of a traditional switch/case statement, THT provides a more flexible match statement.

match value {
    pattern {
        // ...
    }
    pattern {
        // ...
    }
    default {
        // optional fallback
    }
}

Each pattern will be compared to the given value, from top to bottom. If there is a match, that block will be executed and the match block will end.

Each pattern can be:

// Example number
match $age {
    43 {
        print('A Good Age :)');
    }
    $age >= 50 {
        print('Middle Age');
    }
    range(13, 19) {
        print('Teen');
    }
}

// Example string (with one-liner syntax)
match $actor {
    'Tom Hanks': $movieRating += 5;
    r'Baldwin':  $movieRating += 1;
    default:     $movieRating -= 2;
}