Gotchas
The things most likely to surprise you, especially coming from Python or C. Each links to the chapter that explains it.
Names#
- You cannot reuse a name in an inner scope. A local or parameter cannot take the name of another visible local, a parameter, an import or a top-level declaration of the file. Python allows this; Base reports "already in scope". Syntax
- An import takes its name. After
import c, a parameter or local namedcis an error, and the same goes for every imported module name. - Some ordinary-looking words are reserved:
local,type,test,in,with,new,free,none. Syntax - The built-in function and type names cannot be declared:
let format = ...,func print(...)and a parameter namedstrare errors. A struct field may use them. - A file cannot be named after a standard module:
c.lucb,io.lucb,memory.lucb,os.lucb,strings.lucband the others are refused. - A file name must be a valid identifier:
color_space.lucb, notcolor-space.lucb. - A package is not a module.
import luce_stdis an error; import one of its modules:from luce_std import files. Modules and packages - A package called
luce-stdis writtenluce_stdin code.
Layout and syntax#
- Tabs are errors; indent with four spaces. Syntax
- Assignment is a statement, not an expression, and there is no
++or--. Usewhile letwhere C would assign in a condition. Expressions - Comparisons do not chain.
a < b < cis nota < b and b < c. notbinds tightly:not x == 5means(not x) == 5. Writex != 5. Expressions- Conditions must be
bool.if count:andif pointer:are errors. &binds more tightly than==, unlike C:flags & mask == 0is(flags & mask) == 0, which is usually what you meant.
Numbers#
- Overflow traps, in every build.
+,-and*on integers stop the program when the result does not fit, including in--release. Use+%to wrap,+|to saturate,+?to get an optional. Expressions //rounds toward zero, as C does:-7 // 2is-3, where Python gives-4.%matches:-7 % 2is-1./is only for floats. Integers divide with//.u8(x)and(u8)xdiffer.u8(300)traps;(u8)300is44. Expressions- Literal arithmetic is done in the type it is assigned to:
let x: u8 = 200 + 100traps, because 300 does not fit au8. In a cast,(u8)(200 + 100), the sum is computed asi64first and gives 44. - Integers and floats never convert by themselves. Write
f64(count). - Atomic arithmetic wraps instead of trapping, as C's does. Concurrency
Text#
lengthcounts bytes, not characters:"café".lengthis 5. Types- A
strcannot be indexed by position, and there is no+to join strings. Usestrings.formatinto a buffer, or luce-std'scollections.Buffer. - A formatted string is not a value:
let s = f"..."is an error. It goes toprint,strings.format, aWriteror afmtparameter. Types - A format specification takes a number or text:
{n:x}and{name:>8}work, but a value that shows itself throughdisplaytakes none; write{value}. printand C'sprintfcan appear out of order, becauseprintfis buffered. Cmain(arguments: str[])traps on an argument that is not UTF-8. Takec.str[]for file paths. Functions
Types and values#
- Structs are copied on assignment, not shared as Python objects are. Pass a pointer to share one. Structs
- Arrays nest as in C:
u8[3][2]is three arrays of two bytes. Types - A pointer to an array is indexed through
*: withp: u8[4]*, write(*p)[1].p[1]indexes the pointer itself. Memory - An optional must be unwrapped before use, including an optional pointer:
node.next.valuedoes not compile whennextisNode*?. Errors - A
matchon an integer, character or string needs a_arm, and so does amatchon an integer-backed enum, since a combination of flags is not a case. Control flow nonecannot be an enum case, since.nonemeans an empty optional.- A union has no constructor. Declare it and assign a member. Unions
- The vector broadcast
f32[4](x)needs the type written out; it does not work through a type alias. Types hashvalues change between runs; do not store them.
Functions and methods#
- A method that changes its receiver needs a changeable one: calling it on a
letis an error, and the message names the method. Nothing marks such a method; its body does. Functions - A
static funcis called through the type:Point.origin(), notp.origin(). A function in a type withoutstaticis a method, even when it never usesself. Functions - Default argument values must be constants.
- Lambdas cannot capture local variables. Pass state as a parameter or a context pointer. Functions
- A generic function can only use what its constraints promise.
var x: Twith no value is an error for an unconstrainedT. Generics
Errors#
- Every fallible call must be handled with
try,catchorelse; it cannot be ignored, even with_ = .... Errors - A
catchhandler'srecovervalue must have the type of the expression. For a call that returns nothing, the handler needs norecover. - One
trycovers the whole expression after it, every fallible call inside it. - A caught failure's message lasts until its handler finishes. Read it, pass it on or raise it again inside the handler; to keep it, store
strings.copy(failure.message). Errors - A trap cannot be caught, and
deferdoes not run on a trap. defersees variables as they are when it runs, at the end of the block, not when it was written (unlike Go's argument evaluation). Control flow
Memory#
- Memory comes from the current allocator, which
withchanges. A type that allocates must free withfree(...) in self.allocator, not the current one. Memory - Each new thread starts with
memory.heapas its current allocator, not its parent's. Concurrency - Use after free and double free are not detected in a normal build. Build with
--profile diagnostic, or AddressSanitizer through the C backend, to find them. Memory
Tools#
luce-base testruns the tests of one package: the file's and those of the modules of its package it imports, but never a dependency's; with--package, asluc testruns it, every module of the package's too. Testing- A test that fails by an error or a false
assertin its own body is reported and the run continues; any other trap, anassertin a function it calls included, ends the run. --lib -o namewritesname.aandname.h: pass-o libname, not-o libname.a. C-Wturns warnings on; without it, unused code is not reported.check -Wexits with status 1 if it warned. Building