Threadon deliberately stays small. The other pages describe everything that is there; this page is the inverse — the things you will look for and not find. If something here disagrees with the compiler, the compiler wins.
Control flow
- No
switch, nomatch, no pattern matching. It'sif,elif,elseall the way down. - No ternary.
a < b ? x : ydoesn't exist, and neither does anifused as an expression. Everyifis a statement. - No
for…else, noenumerate, nozip. Want an index along with the element? Loop overrange(len(xs))and index with it. - No
do…while, nogoto, no labeledbreak/continue.breakandcontinueonly affect the nearest loop. - Loops reset union narrowing. After a
whileorfor, a union variable reverts to its declared type. See Unions. rangeworks onInt64only. There's no float stepping, no descending convenience beyond a negative step.- Powers are limited. Chained powers like
2 ** 3 ** 2are rejected, and a negative exponent doesn't work. See Operators. - Recursion eats the stack. There's no tail-call optimization; deep recursion fails at runtime. Use
while/forfor long repetition.
Collections and strings
- Only two collection types.
ListandDict, each holding one row of types. There are no sets, no tuples, and no fixed-size arrays. - Lists can grow, but only with the four methods.
append,pop,insert, andremoveexist and mutate the list in place. There is noextend,sort,reverse,clear, or concatenation syntax, and no way to splice one list into another. (Indexing and slicing to read a list do work — see slices.) - Under
--debug, the risky list operations fail loudly. There's no compile-time check:popon an empty list andremoveof a missing element are runtime errors only under--debug. Without--debug, their behavior is unspecified. See Debugging. - No index while iterating.
for x in xsyields only the values. Pair them with an index by hand:for i in range(len(xs))thenxs[i]. - Dicts iterate keys, not pairs.
for k in dgives the key; look the value up yourself. There's noitems()-style iteration and no destructuring. - No membership test.
x in xsisn't an expression; theinkeyword appears only infor. Loop to find an element, and watch a missingDictkey — it reads as the zero value, or aKeyErrorunder--debug. See Types. - Strings are a small feature set. You can join with
+, index and slice, compare by content, turn numbers and bools into text withString(...), convert back with casts, build characters withchr, and interpolate withf"..."/t"..."(see Strings). Missing:len, iteration, searching, replacing, case conversion, trimming, splitting, and any formatting. Characters are read-only —s[0] = "x"is a compile error. - String escapes are minimal. Only
\n,\t,\", and\\(plus{and}inside interpolatedf"..."/t"..."strings). No\xNN,\u, or\0escapes. - No
chartype.chr(27)returns a one-characterString, not a distinct character type with its own conversions. - Floats print with a fixed six decimals. There is no formatting control: no rounding knob, no width, no scientific toggle. See Types.
Numbers and operators
- No bitwise operators. No
&,|,~,<<, or>>; there's no way to manipulate individual bits. - No unary plus.
+nis a compile error — just writen. - No non-decimal literals. No
0x,0b, or0o, and no exponent with a sign (1e-3is invalid). Digits, underscores, a dot, and a plaineare all you get. - No implicit conversions between different types.
1 + 2.5and1 == 1.0are compile errors. The only leniency in the whole language: an integer literal adapts to the type it's assigned to. See Types. - Integer arithmetic wraps. No range checks on
+,-,*, or shifts (there are no shifts). The only overflow you can catch is a string-to-number cast under--debug. See Types. - No math library. No
sqrt,sin,cos,log,floor, orrandom. Operators+ - * / // % **plus the standard library'sabs,max,min,clamp,is_even, andis_oddare the whole arithmetic toolbox. See Std lib. - No complex numbers; the widest type is
Int256/UInt256.
Types, generics, and declarations
- No user-defined generics.
List[T],Dict[K, V], andUnionare built in, but you can't write a generic function or class of your own. - No type inference. There is no
var; every variable and parameter needs its type written out. See Variables. - No enums. A fixed set of named values has to be spelled with constants written by hand — and there are no module-level constants either.
- No
const,immutable, orfinal. Every variable is mutable once declared. - Limited global variables. Module-level variables exist, but the module body is declarative: only variable declarations (with a literal initializer), functions, structs, classes, and
threadstatements are allowed there. A bare statement likex = 99at module level is a compile error — write to globals from inside a function. See Threads. - No
structorclassinside a function. Both are top-level-only declarations. See Structs. - Unions are restrictive by design. You can't assign a union to a concrete variable without narrowing, you can't cast a union, and narrowing resets across branches and loops. The full list is on the Unions page.
NoneTypeis a value, not a void. It can be stored in a variable, passed around, and printed (asNone), but it has no methods and can't take part in arithmetic or comparison —printis the only builtin that accepts it.
Functions
- No overloading. Two functions can't share a name, and imported names can collide. A union parameter is the intended substitute. See Unions.
- No function values. You can't store a function in a variable, pass one to another function, or return one. No closures, no lambdas, nothing higher-order.
- No forward declaration. A function must be defined before it's called, top to bottom in the file. See Functions.
- Same rule inside a class. A method can only call methods declared above it in the class body. The order of method definitions matters.
- No named arguments. Calls are positional. (Default parameter values do exist, so you can omit trailing arguments.)
- One return value. No tuples, no multiple returns, no out-parameters — combine several results in a struct instead.
- Only
printis variadic. Every other function has a fixed arity. - No trailing comma in a parameter list (and none in an import list). Calls and list/dict literals don't mind one.
Classes and structs
- Value semantics. Both classes and structs copy on assignment and on function/method call. A mutation only sticks through a
^reference or a direct field write. See Classes. - No multiple inheritance, no interfaces, no abstract classes, no traits or mixins.
class Dog(Base)names exactly one base. - No static or class methods. Every method starts with
self. - No operator overloading. The only special methods are the constructor
__init__and the printer__str__. Equality and arithmetic on your types can't be hooked (custom iteration works differently — it's a plaindone/value/advancetrio, see Flow). - One constructor. A class has exactly
__init__(or none), no overloads and no destructors. - Foreign classes have a hole. Instances of a foreign-module class (C, C++, Rust, Python) can't be passed to or returned from methods yet. See Classes.
The outside world
- I/O means
printandinput. Stdout and stdin only: no files, no network, no sockets, no pipes. See Builtins. - No command-line arguments.
maintakes none; there's noargv. The only exit signal ismain's return value. See Functions. - No environment variables, and no way to read or set them.
- No strings for dates, times, or regex. Nothing in the standard library touches them.
- No random numbers. There's no clock and no entropy source; generate any randomness yourself from arithmetic.
- Threads are limited. Spawned only at module level, read and write module globals directly with no user-level locks — a read-modify-write race is your problem. There is no async, no mutex, no channel, and no way to wait for a specific thread from inside another. See the Threads page.
Memory and safety
- No garbage collector and no
free. Strings, lists, and dicts allocate heap memory that is never reclaimed while the process runs. A long-running program can only grow. - No raw pointers or pointer arithmetic. The
^reference is the whole pointer story, and it can only be created in a variable declaration (r: T = x^) pointing at a variable.x = y^in an expression doesn't work, and neither does(a + b)^. See References. - Runtime checks require
--debug. Division by zero, bad string-to-number casts, out-of-bounds list reads and string index reads, and missing dict keys are undefined behavior without it. See Debug. - Deep recursion exhausts the stack; there's no way to grow it from Threadon.
Modules and imports
- Only functions, structs, and classes can cross module boundaries. Importing a variable or constant is an error. See Imports.
- No wildcard imports.
from m import *is rejected. - No circular imports.
aimportingbwhilebimportsais a compile error. - Imported names are not namespaced. Collisions between two imported names are same-name conflicts, since overloading doesn't exist.