Style guide
This document describes the preferred style for the Toit language. To learn about Toit's syntax see the syntax summary. To learn about Toit's documentation convention, see the language documentation convention section.
Whitespace and indentation
Indentation in Toit is always with spaces. Tabs are not allowed.
We use two spaces for statements.
When parameters are indented, they should be intented by four spaces:
fun-with-many-params param1 /int param2 /string param3 /Lambda: return ... // Code is again intended by 2.
Arguments are intended by four spaces, unless they are the body of a block or lambda:
The same applies for operators or other reasons when a line gets too long:
Line length
There is no hard line length limit in Toit, but it is often more readable to limit line lengths to 80 or 120 characters.
Block comments can be line-wrapped at any point and should almost always be limited to 80 characters for readability, even in code that is wider for some reason.
When breaking longer lines, the point of lowest precedence should be picked.
my-badly-formatted-function x/num y/num -> num: return x * x * x + y * y // Don't break at high-precedence '*'. * y my-well-formatted-function x/num y/num -> num: return x * x * x // Break at low-precedence '+'. + y * y * y
As seen above prefer to break before operators, not after operators.
This fits well with the ability to use newlines in long argument lists, since argument lists have lower precedence than operators.
// Using newline instead of parentheses to delineate the // single argument to the print function. print unary-function argument
Whitespace around operators
Always surround operators with whitespace.
radians-1:=degrees*2*math.PI/180 // Not enough spaces. radians-2 := degrees * 2 * math.PI / 180 // Better spacing.
Arguments to functions and methods also have single spacing.
For functions with more than one argument this can be hard to read, in which case you should add parentheses or newlines.
my-func x+1 x*1 // Not enough spaces. my-func x + 1 x * 1 // Hard to read. my-func (x + 1) (x * 1) // Easier to read. my-func // Nice uncluttered look with newlines. x + 1 x * 1
Between a line and an end-of-line comment there should be at least two spaces. More can be added for alignment (see above).
Naming
Most names in Toit are named with lower letters and dashes between words.
Classes are named with initial capital letters and camel case.
This applies even if they contain abbreviations that would normally be written in all-caps.
Constants are written in all-caps with dashes:
We prefer not to use abbreviations in API-visible names unless they are very well established.
// Name too abbreviated. f-to-c f/num -> num: return (f - 32.0) / 9 * 5 // Better. fahrenheit-to-celcius fahrenheit/num -> num: return (fahrenheit - 32.0) / 9 * 5
An exception must be made for variables named str
since the name
string
is taken for the string type, but often a better name than
str
can be found.
Package-private names end with an underscore.
Comments
A single line comment is written as a full sentence, starting with a capital
letter and ending with a period (.). At least two spaces should separate the
//
from code, and a space separates the //
from the text of the comment.
See also documentation comments.
Declarations
Variables and members are not given an initial value unless it makes sense.
z := some-value x := 0 // No need to give x an inital value. y /int := ? // Compiler will check it is initialized before being used. if z == 1: x = 1 y = 2 else: x = 2 y = 1
Similarly for members:
class Foo: x /int? := null // Don't assign null unless you want this default y /int := ? // Value comes from constructor. constructor .x .y: // Compiler will check that y is initialized.
Classes
Getters and setters
In Toit, getters and setters have the same syntax (for users of a class) as public member variables. Therefore there is no need to write trivial setters and getters:
class UnneededPrivacy: // No point in making this private since it has a trivial // getter and setter. x_ /int := ? // Private member variable. constructor x/int: x_ = x // Getter. x -> int: return x_ // Setter. x= value/int -> none: x_ = value
Instead just make the member public:
If you later need to intercept the setter (for example for logging), you can always
change the Simple
to the implementation used by UnneededPrivacy
without having to change users of the class.
Types
Elements of public APIs should be typed. Internal variables should be typed where it aids readability and according to taste. It is often useful to type parameters, as they cannot be inferred by the compiler.
Types in argument lists are written without spaces in order to group the arguments visually:
Types of
instance variables
and locals are written with a space
before the /
:
Literals
For list literals on multiple lines put a comma on every line, even the last:
As seen above, the closing bracket is dedented to the initial indentation.
If all values are in the 0-255 range and you don't expect to modify the list with a non-byte value, consider using a ByteArray literal:
Loops
For simple zero-to-n loops prefer repeat
to for
-loops.
for i := 0; i < n; i++: // No need for a for-loop. print i n.repeat: // Easier to read and actually faster. print it
If possible use the iteration built-in to the collection:
for i := 0; i < list.size; i++: // Not using the collection's own iterator. print list[i] list.size.repeat: // Not using the collection's own iterator. print list[it] list.do: // Good. print it
In loop bodies more than one or two lines, give the iteration variable
a name instead of just using it
: