Appendix A: Language Reference
Quick Reference
This appendix is your cheat sheet. When you forget syntax or need to look up a feature quickly, start here.
Keywords
fn Function definition
struct Structure definition
enum Enumeration definition
type Type alias
var Mutable variable
const Immutable variable
if Conditional
else Alternative branch
match Pattern matching
while Loop
for Loop
break Exit loop
continue Skip iteration
return Return from function
import Import module
pub Public visibility
spawn Concurrent task
channel Communication channel
some Option variant
none Option variant
ok Result variant
err Result variantOperators
Arithmetic
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulo (remainder)+ also concatenates strings, and it accepts an int on either side - the int is converted to its decimal text. This is intentional:
fn main() {
print(5 + "x") // 5x
print("x" + 5) // x5
}float and bool are not converted; call .to_string() on those. For anything longer than a short label prefer ${} interpolation - see Strings.
Comparison
== Equal
!= Not equal
< Less than
<= Less than or equal
> Greater than
>= Greater than or equalLogical
and Logical AND
or Logical OR
not Logical NOTOther
= Assignment
. Member access
:: Static access
? Error propagation
[] IndexingTypes
Primitive Types
int 64-bit integer
float 64-bit floating point
string UTF-8 string
bool Boolean (true/false)Compound Types
[T] Array of T
HashMap<K, V> Hash map from K to V
Option<T> Optional value (concrete: OptionInt, int?, ...)
ResultInt Result-or-error (also ResultString, ResultFloat, ResultBool)Type Syntax
var x: int = 42 // Explicit type
y = 42 // Inferred type
const PI: float = 3.14159 // Constant with typeVariables
Declaration
mutable = 10 // Mutable
const immutable = 20 // ImmutableScope
{
inner = 10 // Scoped to block
}
// inner not accessible hereShadowing
x = 5
x = x + 1 // Shadows previous x
var x = "hello" // Can change typeFunctions
Definition
fn function_name(param1: Type1, param2: Type2) -> ReturnType {
// body
return value
}Examples
fn add(a: int, b: int) -> int {
return a + b
}
fn greet(name: string) -> int {
print("Hello, " + name)
return 0
}Generic Functions
fn identity<T>(x: T) -> T {
return x
}
fn swap<T>(a: T, b: T) -> (T, T) {
return (b, a)
}Structs
Definition
struct StructName {
field1: Type1,
field2: Type2
}Creation
var instance = StructName {
field1: value1,
field2: value2
}Methods
fn StructName.method_name(self) -> ReturnType {
return self.field1
}Generic Structs
struct Container<T> {
value: T
}Enums
Definition
enum EnumName {
VARIANT1,
VARIANT2,
VARIANT3
}to_string
enum Color { Red, Green, Blue }
Color.Red.to_string() // "Red"
c = Color.Blue
c.to_string() // "Blue"With Data
Variants can carry payloads:
enum Shape {
Circle(int),
Rect(int, int),
Empty
}Type parameters on your own enums (enum Result<T, E>) are not supported yet - the compiler rejects them. Option<T> and Result<T, E> are built in, so you get the two you actually need without declaring them:
fn find(k: int) -> Option<int> {
if k > 0 { return Some(k) }
return None
}
fn parse(s: string) -> Result<int, string> {
if s.len() == 0 { return Err("empty") }
return Ok(s.to_int())
}
fn main() -> int {
match find(3) {
Some(v) => print(v),
None => print("none")
}
match parse("7") {
Ok(n) => print(n),
Err(e) => print(e)
}
return 0
}Control Flow
If Statement
if (condition) {
// true branch
} else if (other_condition) {
// else if branch
} else {
// else branch
}While Loop
while (condition) {
// body
}For Loop
for (var i = 0; i < 10; i = i + 1) {
// body
}For-in Loop
for item in array { }
for i in 0..10 { }
for i, v in array { } // indexed iterationMatch Expression
match value {
pattern1 => action1,
pattern2 => action2,
_ => default_action
}Pattern Matching
Literals
match x {
0 => "zero",
1 => "one",
_ => "other"
}Enums
match result {
ok(value) => use_value(value),
err(message) => handle_error(message)
}Ranges and Or-Patterns
match n {
1 | 3 | 5 => "odd",
1..5 => "small (exclusive end)",
1..=5 => "small (inclusive end)",
_ => "other"
}Guards
match n {
_ if n < 0 => "negative",
0 => "zero",
_ => "positive"
}Collections
Arrays
arr = [1, 2, 3, 4, 5]
arr[0] // Access
arr.len() // Length
arr.push(6) // Append
arr.contains(3) // Check membershipHashMaps
map = {"key1": 1, "key2": 2}
map["key1"] // Access
map["key3"] = 3 // Insert
map.has("key1") // Check key
map.remove("key2") // Remove
map.len() // SizeHashSets
set = {:"a", "b", "c"}
set.contains("a") // Check membership
set.insert("d") // Add
set.remove("b") // Remove
set.len() // SizeError Handling
Result Type
fn operation() -> Result<int, string> {
if (error_condition) {
return Err("error message")
}
return Ok(42)
}Option Type
fn find(arr: [int], target: int) -> Option<int> {
// ...
if (found) {
return some(index)
}
return none
}Error Propagation
fn chain() -> Result<int, string> {
var x = operation1()?
var y = operation2(x)?
return Ok(y)
}Modules
Import
import module_name
import path.to.module
import module as aliasExport
pub fn public_function() -> int {
return 0
}
fn private_function() -> int {
return 0
}Extension Methods
Definition
fn TypeName.method_name(self) -> ReturnType {
return self.field
}Static Methods
fn TypeName.static_method() -> ReturnType {
return value
}Concurrency
Spawn
spawn function_call() // fire and forget
var f = spawn function_call() // keep a handle
var result = await f // wait for the resultChannels
ch = channel(4) // capacity 4
ch.send(42)
value = ch.recv()
ch.close()Type Aliases
type UserId = int
type Email = stringComments
// Single-line comment
// Multi-line comments use
// multiple single-line commentsString Escapes
"\n" Newline
"\t" Tab
"\\" Backslash
"\"" QuoteOperator Precedence
From highest to lowest:
- Method call (
.), indexing ([]) - Unary (
not,-) - Multiplication (
*,/,%) - Addition (
+,-) - Comparison (
<,<=,>,>=) - Equality (
==,!=) - Logical AND (
and) - Logical OR (
or) - Assignment (
=)
Use parentheses to override precedence.
Common Patterns
Error Handling
match result {
ok(value) => use_value(value),
err(msg) => handle_error(msg)
}Option Handling
match option {
some(value) => use_value(value),
none => use_default()
}Iteration
for (var i = 0; i < arr.len(); i = i + 1) {
process(arr[i])
}Method Chaining
var result = text.trim().upper().reverse()Naming Conventions
snake_case Variables, functions
SCREAMING_SNAKE Constants
PascalCase Types (structs, enums)File Extensions
.wyn Wyn source fileCompilation
wyn run program.wyn # Compile and run
wyn build program.wyn # Build a binary
./program # Run it
wyn help # HelpCommon Mistakes
Leaving the Return Type Off
Wyn infers a return type from the return statements, so this compiles and returns an int:
fn add(a: int, b: int) {
return a + b
}Write it down anyway. It states the contract, and the checker then catches a body that drifts away from it instead of quietly changing the function's type:
fn add(a: int, b: int) -> int {
return a + b
}Parentheses in Conditions Are Optional
// Both are fine
if x > 0 { }
if (x > 0) { }Ignoring Result/Option
// Wrong
var value = option // Option<T>, not T
// Right
match option {
some(value) => use_value(value),
none => handle_none()
}Forgetting pub
// Wrong (if you want it public)
fn helper() -> int { }
// Right
pub fn helper() -> int { }Quick Examples
Hello World
fn main() -> int {
print("Hello, World!")
return 0
}Read File
fn read_file(path: string) -> ResultString {
if not File.exists(path) {
return Err("file not found: " + path)
}
return Ok(File.read(path))
}
fn main() -> int {
result = read_file("data.txt")
match result {
ok(contents) => print(contents),
err(msg) => print("Error: " + msg)
}
return 0
}HTTP Request
fn main() -> int {
result = Http.get("https://api.example.com/data")
match result {
ok(response) => print(response.body),
err(msg) => print("Error: " + msg)
}
return 0
}Concurrent Tasks
fn producer(ch: int) -> int {
Task.send(ch, 42)
return 0
}
fn main() -> int {
ch = channel(4)
f = spawn producer(ch)
value = ch.recv()
print(value)
await f
return 0
}This reference covers the essential syntax and patterns. For detailed explanations, see the main chapters. For complete API documentation, see Appendix B.