Skip to content

Naming and style convention

Karl Zylinski edited this page Oct 14, 2025 · 18 revisions

Any code that goes into the examples repository should follow these conventions.

Exceptions: If you are making a 1:1 port of an example from another language, then it sometimes makes sense to go against the naming conventions.

Naming convention

In general, Ada_Case for types and snake_case for values

Case
Import Name snake_case (but prefer single word)
Types Ada_Case
Enum Values Ada_Case
Procedures snake_case
Local Variables snake_case
Constant Variables SCREAMING_SNAKE_CASE

Style convention

Compile cleanly with flags -vet -strict-style -vet-tabs -disallow-do -warnings-as-errors

These flags check for things such as:

  • Unused variables
  • Shadowing
  • That you use tabs for indentation

And much more. See odin build -help for a description of each flag.

Opening brace at end-of-line

some_proc :: proc() {
}

Some_Type :: struct {
}

Prefer val := Some_Type { over val: Some_Type = {

Example, do this:

cam := Camera {
	position = { 50, 50, 10 },
}

Not this:

cam: Camera = {
	position = { 50, 50, 10 },
}

Exception: val: f32 = 5 and val := f32(5) are equally reasonable.

Prefer using type inference

Do this:

sound := load_sound(filename)

Not this:

sound: Sound = load_sound(filename)

There are times when being explicit about the type can be helpful. But only do that if it really helps the example somehow.

Also, when creating a union and setting it to a specific variant on a single line, then you need to do var: Some_Union = Some_Union_Variant {}

Use initializers when possible

Do this:

cam := Camera {
	position = { 50, 50, 10 },
	offset = { 10, 20 },
	zoom = 2,
}

Not this:

cam: Camera
cam.position = { 50, 50, 10 }
cam.offset = { 10, 20 }
cam.zoom = 2

Write val: int and val := 5

Not val : int or val:= 5 or val: = 5

Don't overuse defer

Use defer when there are multiple ways to leave a scope and you need to run some code regardless of which path is taken. Do not use it if there is only one way to leave a scope. Defer has a cost: The code is no longer linear, therefore harder to read.

Use tabs for indentation, but use spaces for alignment

In this example we've broken a procedure parameter list into two lines, because it has a lot of parameters. We use tabs for the indentation of the lines within the procedure. But we use spaces to align is: f32.... We use spaces for the alignment so that it is the same for everyone. Otherwise a: int and is: f32 won't align unless other people have the same tab size as you.

some_proc :: proc(a: int, lot: f32, of: string, parameters: f64,
                  is: f32, fun: string) {
	fmt.println(fun)
}

Image where you can see the spaces and tabs: image

If the proc in the example above is nested, then things are a bit more complex:

main :: proc {
	some_proc :: proc(a: int, lot: f32, of: string, parameters: f64,
	                  is: f32, fun: string) {
		fmt.println(fun)
	}
	
	some_proc(0, 0, "hello", 0, 0, "hello")
}

See this image for how the tabs and spaces look: image

Note how the line that uses alignment spaces has tabs and spaces mixed on a single line.