Intermediate Features
- Summary
- Optional Argument Parens
- Keyword Shortcuts
- Quoted (Quick) Lists
- One-Liners
- Operators
- Regular Expressions
- Anonymous Functions
- Argument Typing
- Try/Catch
- Match
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 }}! }
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.
// 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 });
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 }
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:
- An exact value (e.g. number, string)
- An expression. If it is
true
, the pattern is a match. - A regular expression.
- A List. The pattern is a match if the value is an element of the List.
// 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; }