THT is in early Beta. We welcome contributors & feedback.

Syntax Cheat Sheet (5 minutes)

A quick overview of the THT syntax, for experienced programmers.

// This is a one-line comment

/*
    This is a block comment
*/


//========================================================
//                       STRINGS
//========================================================

// Strings are created with a single-quote (')
'Hello World!';

// Strings are joined with the 'stringy' operator (~)
'Hello, ' ~ ' World!';  //= 'Hello, World!'

// Backticks (`) are converted to single quotes
'That`s brilliant!';  //= 'That's brilliant!'


//========================================================
//                   FLAGS / EQUALITY
//========================================================

// Flags (aka Booleans)
true;
false;

// Negation
!true;  //= false
!false; //= true

// Equality check with '=='.  It acts like '===' in PHP
// and JavaScript. (no type coercion)
1 == 1;    //= true
1 == '1';  //= false

// Inequality
1 != 1; //= false
1 != 2; //= true

// Comparison
1 < 2;  //= true
1 > 2;  //= false
2 >= 2; //= true
2 <= 2; //= true


//========================================================
//                     VARIABLES
//========================================================

// Variables are declared with 'let'.
// They must always be initialized with a value.
let letters = 'abcde';
let year = 2020;

// built-in types have methods
'abdce'.length();   //= 5
'abcde'.reverse();  //= 'edcba'

// short-hand math assignment
year += 1;  // same as 'year = year + 1'

let greeting = 'Hi';
greeting ~= '!';  // 'Hi!' (stringy assignment)


//========================================================
//                       LISTS
//========================================================

// Lists are an ordered sequence of values, of any type.

let colors = ['red', 'blue', 'yellow'];

// Built-in methods
colors.length();    //= 3
colors.join(', ');  //= 'red, blue, yellow'

// Indexes are zero-based
colors[0];  //= 'red'
colors[1];  //= 'blue'

// Directly assign a value
colors[2] = 'orange';

// Add items
colors.add('green');      //= Add to the end
colors.add('purple', 0);  //= Add to the front

// Remove items
colors.remove();   //= 'green'  (last item)
colors.remove(0);  //= 'purple' (first item)

// List add operator - same as add()
colors #= 'green';


//========================================================
//                        MAPS
//========================================================

// Maps are key/value pairs.
// They are like associative arrays in PHP.
// They use JavaScript object literal notation.

let user = {
    name: 'Gilly Green',
    age: 25,  // trailing commas are ok in multiline maps
};

user['age'];  //= 25

// Assign new fields.
user['address'] = '123 Rainbow Road';

// Or use dot notation
user.address = '123 Rainbow Road';

// Dot (.) notation is strict.
user.job;  // ERROR. 'job' key doesn't exist.

// Index notation ([]) is not strict.
user['job'];  // OK. Returns '', a safe falsey value.



//========================================================
//                       IF / ELSE
//========================================================

if (condition1) {
    // ...
} else if (condition2) {
    // ...
} else {
    // ...
}


//========================================================
//                       LOOPS
//========================================================

// 'for in' loops iterate through a list.
for (color in colors) {
    print(color);
}

// To loop through numbers, use the 'range' function.
for (n in range(1, 4)) {
    print('Color #' ~ n);
}

// A bare 'for' repeats forever until you exit with 'break'.
// Use this instead of 'while'.
for {
    let color = Palette.getNextColor();
    if (!color) { break; }
    if (color.isBoring) { continue; }
    print(color.name);
}


//========================================================
//                      FUNCTIONS
//========================================================

// Declaring a function
function hello(name) {
    return 'Hello, ' ~ name ~ '!'
}
hello('Mr. Yellow');  //= 'Hello, Mr. Yellow!'


// An optional argument with default value
function hello(name, greeting = 'Hello') {
    return greeting ~ ', ' ~ name ~ '!'
}
hello('Mr. Yellow', 'Hi');  //= 'Hi, Mr. Yellow!'


//========================================================
//                    SPECIAL STRINGS
//========================================================

// LockStrings are prefixed with 'L'.
// They are secure literal strings that take placeholder
// values via fill().
let sql = L'select * from user where id = {}';
sql.fill(userId);
let user = Db.select(sql);

// Regular Expression strings are prefixed with 'R'.
// They ignore whitespace by default.
let regex = R'\w+ \s* = \s* (\d+)';
'foo=1234'.match(regex)[1]; //= '1234'


//========================================================
//                       MODULES
//========================================================

// You can organize functions into separate module files.
// Modules names are always UpperCamelCase.

// --------------- modules/ForumUser.tht ---------------

function hello(name) {
    print('Hello, ' ~ name ~ '!');
}

// ---------------------- main.tht -----------------------

// Modules are automatically imported from the 'modules'
// folder when called.
ForumUser.hello('Mr. Yellow');  //= 'Hello, Mr. Yellow!'

// Every file has its own namespace.
hello('Mr. Yellow');  // ERROR.  Function not found.


//========================================================
//              THINGS THT DOES NOT HAVE
//========================================================

// THT avoids features that could be considered redundant,
// too ambiguous, or uncommonly used for web development.

// Feature     Try this instead...

++ --          // += 1 or -= 1
for(;;)        // for (i in list) { ... }
while          // for { ... }
switch/case    // if/else or Map lookup
^ | &          // TBD
null           // empty value (e.g. '', 0, false)
               // or Result object