WebsiteTemplate/quickref/odin.html
2026-01-25 11:33:37 -04:00

416 lines
10 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self' data:; img-src 'self' data:; connect-src 'self'; base-uri 'self'; form-action 'self' https://defcon.social https://bsky.app;">
<meta http-equiv="X-Content-Type-Options" content="nosniff">
<link rel="stylesheet" href="../assets/css/style.css">
<link rel="icon" type="image/x-icon" href="../favicon.ico">
<script>
// Apply theme immediately to prevent flash
(function() {
const theme = localStorage.getItem('theme') ||
(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
})();
</script>
<title>Odin Quickstart Reference - Quick Reference - Launch Pad</title>
</head>
<body>
<button class="theme-toggle" id="themeToggle" aria-label="Toggle dark mode">
<svg class="theme-icon theme-icon-moon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
<svg class="theme-icon theme-icon-sun" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>
</button>
<br/><br/>
<div class="name">
__ _______________________ _________._________________________
\_ _____/ \______ \ / _ \ / _____/ / _____/ | | \_ _____/
| __) | _/ / /_\ \ / \ ___ / \ ___ | | | __)_
| \ | | \ / | \ \ \_\ \ \ \_\ \ | |___ | \
\___ / |____|_ / \____|__ / \______ / \______ / |_______ \ /_______ /
\/ \/ \/ \/ \/ \/ \/
</div>
<div class="blog-page-header">
<div class="blog-header-content">
<a href="/quickref" class="back-link" title="Back to Quick Reference">
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" viewBox="0 0 24 24" class="home-icon"><path fill="currentColor" d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></svg>
</a>
<h1 class="blog-page-title">Odin Quickstart Reference</h1>
</div>
</div>
<div class="blog-post-container">
<div class="blog-posts-container" style="max-width: 900px; margin: 0 auto;">
<div class="blog-post">
<div class="blog-post-content">
<p><a href="index.html">← Back to quick reference</a></p>
<p><a href="../index.html">← Home</a></p>
<hr>
<p>Quick reference guide for Odin. Essential syntax, types, control flow, and common patterns for the Odin programming language.</p>
<hr>
<h2>Hello World</h2>
<pre><code>package main
import "core:fmt"
main :: proc() {
fmt.println("Hello, World!") // Odin keeps it clean and readable.
}</code></pre>
<hr>
<h2>Variables</h2>
<pre><code>x: int = 42
name: string = "Alice"
flag: bool = true
pi: f64 = 3.14
// Type inference with :=
y := 100 // Compiler infers int
text := "Hello" // Compiler infers string
// Multiple declarations
a, b, c: int = 1, 2, 3
</code></pre>
<hr>
<h2>Control Flow</h2>
<h3>If/Else</h3>
<pre><code>if x > 10 {
fmt.println("x is big")
} else {
fmt.println("x is small")
}
if x > 10 {
fmt.println("big")
} else if x > 5 {
fmt.println("medium")
} else {
fmt.println("small")
}
// If as expression
result := "big" if x > 10 else "small"
</code></pre>
<h3>For Loops</h3>
<pre><code>for i in 0..5 { // 0 to 4, exclusive
fmt.println(i)
}
for i in 0..=5 { // 0 to 5, inclusive
fmt.println(i)
}
nums := []int{1, 2, 3}
for n in nums {
fmt.println(n)
}
for n, i in nums { // Value and index
fmt.printf("%d: %d\n", i, n)
}
// Traditional C-style
for i := 0; i < 5; i += 1 {
fmt.println(i)
}
</code></pre>
<h3>While Loops</h3>
<pre><code>y := 10
for y > 0 {
y -= 1
fmt.println(y)
}
// Infinite loop
for {
if y <= 0 {
break
}
y -= 1
}
</code></pre>
<hr>
<h2>Functions</h2>
<pre><code>add := fn(a: int, b: int) -> int {
return a + b
}
fmt.println(add(2, 3))
// Named function
add :: proc(a: int, b: int) -> int {
return a + b
}
// Multiple return values
divide :: proc(a: f64, b: f64) -> (f64, bool) {
if b == 0 {
return 0, false
}
return a / b, true
}
result, ok := divide(10.0, 2.0)
if ok {
fmt.println(result)
}
// Procedures (no return value)
greet :: proc(name: string) {
fmt.printf("Hello, %s!\n", name)
}
</code></pre>
<hr>
<h2>Arrays / Slices</h2>
<h3>Slices</h3>
<pre><code>nums: []int = [1, 2, 3] // Slice literal, mutable and resizable
for n in nums {
fmt.println(n)
}
// Append to slice
append(&nums, 4)
append(&nums, 5, 6)
// Length and capacity
len(nums) // Current length
cap(nums) // Capacity
// Make slice with capacity
nums := make([]int, 0, 10) // Length 0, capacity 10
</code></pre>
<h3>Arrays</h3>
<pre><code>arr: [3]int = {1, 2, 3} // Fixed-size array
arr := [3]int{1, 2, 3} // Shorthand
// Array size inference
arr := [?]int{1, 2, 3} // Compiler infers size 3
</code></pre>
<h3>Maps</h3>
<pre><code>import "core:map"
person := make(map[string]string)
map.set(&person, "name", "Alice")
map.set(&person, "age", "30")
name, found := map.get(&person, "name")
if found {
fmt.println(name)
}
// Map literal
person := map[string]string{
"name" = "Alice",
"age" = "30",
}
</code></pre>
<hr>
<h2>Strings</h2>
<pre><code>text := "Hello, World!"
text := `Multiline
string
literal`
// String operations
len(text) // Length in bytes
fmt.printf("%s\n", text) // Print formatted
// String concatenation
greeting := "Hello, " + name
// String formatting
name := "Alice"
greeting := fmt.tprintf("Hello, %s!", name)
</code></pre>
<hr>
<h2>Structs</h2>
<pre><code>Person :: struct {
name: string,
age: int,
}
person := Person{
name = "Alice",
age = 30,
}
fmt.printf("%s is %d\n", person.name, person.age)
// Methods
Person :: struct {
name: string,
age: int,
}
greet :: proc(p: Person) {
fmt.printf("Hello, I'm %s\n", p.name)
}
person := Person{name = "Alice", age = 30}
greet(person)
</code></pre>
<hr>
<h2>Enums</h2>
<pre><code>Direction :: enum {
Up,
Down,
Left,
Right,
}
dir := Direction.Up
switch dir {
case .Up:
fmt.println("Going up")
case .Down:
fmt.println("Going down")
case .Left:
fmt.println("Going left")
case .Right:
fmt.println("Going right")
}
</code></pre>
<hr>
<h2>Unions</h2>
<pre><code>Value :: union {
int,
f64,
string,
}
v: Value = 42
v = 3.14
v = "hello"
switch v in v {
case int:
fmt.printf("Integer: %d\n", v)
case f64:
fmt.printf("Float: %f\n", v)
case string:
fmt.printf("String: %s\n", v)
}
</code></pre>
<hr>
<h2>Error Handling</h2>
<pre><code>import "core:fmt"
// Using optional types
divide :: proc(a: f64, b: f64) -> (result: f64, ok: bool) {
if b == 0 {
return 0, false
}
return a / b, true
}
result, ok := divide(10.0, 2.0)
if ok {
fmt.printf("Result: %f\n", result)
} else {
fmt.println("Division by zero")
}
// Using error types
Error :: enum {
None,
Division_By_Zero,
Invalid_Input,
}
divide :: proc(a: f64, b: f64) -> (f64, Error) {
if b == 0 {
return 0, .Division_By_Zero
}
return a / b, .None
}
</code></pre>
<hr>
<h2>File Operations</h2>
<pre><code>import "core:os"
import "core:fmt"
// Reading
data, ok := os.read_entire_file("file.txt")
if ok {
fmt.println(string(data))
}
// Writing
content := "Hello, World!"
os.write_entire_file("file.txt", transmute([]u8)content)
</code></pre>
<hr>
<h2>Memory Management</h2>
<pre><code>import "core:mem"
// Allocators
allocator := context.allocator
// Allocate memory
ptr := new(int)
ptr^ = 42
// Free memory
free(ptr)
// Using different allocators
temp_allocator := mem.temp_allocator()
</code></pre>
<hr>
<h2>Tips</h2>
<ul>
<li>Odin is strongly typed; type declarations are explicit.</li>
</ul>
<ul>
<li>Loops often use ranges like <code>0..5</code> (exclusive of 5); use <code>0..=5</code> for inclusive.</li>
</ul>
<ul>
<li><code>fmt.scanf</code> or <code>read_string</code> can handle user input:
<pre><code>import "core:fmt"
import "core:os"
input: [256]u8
n, _ := os.read(os.stdin, input[:])
text := string(input[:n])</code></pre>
</li>
</ul>
<ul>
<li>Slices (<code>[]Type</code>) are dynamic arrays, arrays (<code>[N]Type</code>) are fixed-size.</li>
</ul>
<ul>
<li>Functions are first-class and can be assigned to variables.</li>
</ul>
<ul>
<li>Use <code>:=</code> for type inference, <code>:</code> for explicit typing.</li>
</ul>
<ul>
<li>Procedures (<code>proc</code>) are functions; use <code>fn</code> for function values.</li>
</ul>
<ul>
<li>Multiple return values are common; use tuples or named returns.</li>
</ul>
<ul>
<li>Use <code>^</code> to dereference pointers, <code>&amp;</code> to take addresses.</li>
</ul>
<ul>
<li>Odin uses explicit memory management; understand allocators for advanced usage.</li>
</ul>
<ul>
<li>Struct literals use <code>=</code> for field assignment: <code>Person{name = "Alice"}</code>.</li>
</ul>
<ul>
<li>Use <code>switch</code> for pattern matching on enums and unions.</li>
</ul>
<ul>
<li>Import packages with <code>import "package:name"</code>; core library uses <code>"core:"</code> prefix.</li>
</ul>
</div>
</div>
</div>
</div>
<script async type="text/javascript" src="../blog/analytics.js"></script>
<script src="../theme.js"></script>
</body>
</html>