416 lines
10 KiB
HTML
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>&</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>
|
|
|