Basics
This page covers the pieces every Tessel program is made of: comments, printing, constants and variables, literal values, and operators. If you have written code in Swift, Kotlin, JavaScript or a similar language, most of it will look familiar.
A first program
Section titled “A first program”// Say hello, then do a little arithmetic.fn main() { let name = "Tessel" print("Hello, {name}!")
var total = 0 for i in 0..5 { total += i } print("The sum of 0..5 is {total}")}Run it with tessel run hello.tsl, and it prints:
Hello, Tessel!The sum of 0..5 is 10A program without a window starts at fn main(). It takes no parameters and
returns nothing. (A program with a window starts at an app instead; see
Programs and files.)
print writes one value to the terminal, followed by a new line. It accepts
an Int, Float, Bool, String or an enum value. To print several
values, put them in one string with {…}, as shown below.
Comments
Section titled “Comments”A comment starts with // and runs to the end of the line. It can be on its
own line or after code:
// This whole line is a comment.let width = 20 // and this is a comment after some codeThere are no block comments (/* … */). To comment out several lines, put
// in front of each one.
Constants and variables
Section titled “Constants and variables”Use let for a value that never changes, and var for one that does:
let name = "Ada" // a constantvar score = 0 // a variablescore = 10score += 5print("{name} has {score} points")Every let and var needs a starting value. Tessel works out the type from
that value, so score above is an Int. You can also write the type
yourself after a colon:
let ratio: Float = 3 // 3 is read as 3.0 herevar names: [String] = [] // an empty list needs its type written outChanging a let is an error that tells you to use var instead:
let limit = 10limit = 20error: can't change `limit`, which is a constant = help: declare it with `var` to be able to change itVariables live inside functions (and state lives inside views). There are
no global variables: a let or var at the top level of a file is an
error. If you need a value that the whole program shares, write a function
that returns it:
fn maxPlayers() -> Int { 4}Names are made of letters, digits and _, and can’t start with a digit. The
usual style is lowerCamelCase for variables and functions, and
UpperCamelCase for types and views.
Literals
Section titled “Literals”| Kind | Examples | Type |
|---|---|---|
| Whole numbers | 0, 42, -7, 1_000_000 | Int |
| Decimal numbers | 3.14, 0.5, 2.0, 1_000.25 | Float |
| Truth values | true, false | Bool |
| Text | "hello", "Total: {n}" | String |
| No value | nil | an optional, see Optionals |
| Lists | [1, 2, 3], [] | [Int] |
| Dictionaries | ["a": 1], [:] | [String: Int] |
You can put _ anywhere in a number to make it easier to read:
1_000_000 is one million.
A decimal number needs digits on both sides of the point: write 0.5, not
.5, and 2.0, not 2..
A whole-number literal takes its type from where it is used. Where a Float
is expected, 3 means 3.0, so you rarely have to write .0:
let width: Float = 3print(width) // 3.0print(1 + 2.5) // 3.5This only applies to literals. A variable never changes type by itself; see
Types for converting between
Int and Float.
Strings
Section titled “Strings”A string is text between double quotes. It must end on the same line it starts on.
Interpolation
Section titled “Interpolation”Put any expression inside { and } to insert its value into the text:
let apples = 3let price = 2print("{apples} apples cost {apples * price} coins")3 apples cost 6 coinsYou can interpolate an Int, Float, Bool, String, Range or enum
value.
Lists, structs and optionals can’t go in directly; for example, use
{list.count}, {names.joined(separator: ", ")} or {nickname ?? "none"}
instead.
Escapes
Section titled “Escapes”A backslash starts an escape sequence:
| Escape | Means |
|---|---|
\n | new line |
\t | tab |
\r | carriage return |
\" | a double quote |
\\ | a backslash |
\{ and \} | a literal brace, not an interpolation |
print("Line one\nLine two")print("She said \"hi\"")print("Path: C:\\temp")print("Use \{name\} to insert a value")Line oneLine twoShe said "hi"Path: C:\tempUse {name} to insert a valueAny other character after a backslash is an error.
Operators
Section titled “Operators”Arithmetic
Section titled “Arithmetic”| Operator | Meaning | Example | Result |
|---|---|---|---|
+ | add | 7 + 2 | 9 |
- | subtract | 7 - 2 | 5 |
* | multiply | 7 * 2 | 14 |
/ | divide | 7 / 2 | 3 |
% | remainder | 7 % 2 | 1 |
-x | negate | -7 | -7 |
Both sides must have the same type. Dividing two Ints gives an Int and
drops the fraction (it rounds toward zero, so -7 / 2 is -3). For a
decimal result, convert first: Float(7) / 2 is 3.5. % works on
Floats too.
+ also joins two strings or two lists:
let greeting = "Hello, " + "world"let numbers = [1, 2] + [3]Int arithmetic is checked. If a result doesn’t fit in an Int, or you
divide an Int by zero, the program stops with an error; see
Runtime errors.
Comparison
Section titled “Comparison”| Operator | Meaning |
|---|---|
== | equal |
!= | not equal |
< <= | less than, less than or equal |
> >= | greater than, greater than or equal |
== and != work on almost every type, including strings, lists, structs,
enums and optionals. <, <=, > and >= work on numbers and strings
(strings compare in dictionary order, so "apple" < "banana").
Comparisons can’t be chained: write a < b && b < c, not a < b < c.
| Operator | Meaning |
|---|---|
&& | and: true if both sides are true |
|| | or: true if either side is true |
! | not: flips true and false |
let age = 30let member = falseprint(age >= 18 && !member)The operands must be Bools. Tessel doesn’t treat 0 or "" as false.
Assignment
Section titled “Assignment”| Operator | Same as |
|---|---|
x = v | set x to v |
x += v | x = x + v (numbers, strings and lists) |
x -= v | x = x - v |
x *= v | x = x * v |
x /= v | x = x / v |
Assignment is a statement, not an expression: you can’t write
a = b = 0 or use x += 1 as a value. The left side can be a variable, a
field (player.score += 1) or an item (scores[0] = 10).
Ranges
Section titled “Ranges”a..b is the range of whole numbers from a up to, but not including, b.
You use it with for:
for i in 0..3 { print(i) // prints 0, 1, 2}If b is not greater than a, the range is empty and the loop body doesn’t
run. There is no inclusive range operator; write 1..(n + 1) to include
n.
A range is a value like any other, of type Range. You can store it in a
variable, pass it to a function, compare two ranges with ==, and print it:
let lines = 2..5for i in lines { print(i) // prints 2, 3, 4}print(lines) // 2..5print(lines == 2..5) // trueTo repeat something without using the number, name the loop variable _:
for _ in 0..3 { … }.
Other operators
Section titled “Other operators”These are covered on their own pages:
??gives a default for a missing optional value, and?.reads a member only if there is a value. See Optionals..reads a field or calls a method,()calls a function, and[]reads an item from a list or dictionary.
Precedence
Section titled “Precedence”From lowest to highest. Operators on the same row are applied left to right,
except ??, which groups to the right.
| Operators |
|---|
|| |
&& |
== != < <= > >= |
.. |
?? |
+ - |
* / % |
! - (prefix) |
. ?. () [] |
Because ?? is lower than +, count ?? 0 + 1 would mean
count ?? (0 + 1), which is rarely what’s meant. So Tessel asks for
parentheses when ?? is followed by arithmetic: write (count ?? 0) + 1, or
count ?? (0 + 1) if that’s what you mean.
Lines and semicolons
Section titled “Lines and semicolons”A statement ends at the end of its line. Tessel doesn’t use semicolons; a
; is an error. Put each statement on its own line.
A statement can still span several lines:
- while a
(or[is open, - after an operator such as
+,&&or=, - when the next line starts with
., which continues a chain of calls.
let total = 1 + 2 + 3let names = [ "Ada", "Grace",]let shout = names .joined(separator: " and ") .uppercase()print(shout)A trailing comma after the last item in a list, like "Grace", above, is
allowed.