Constants & Enums
Constants and enums define fixed values that cannot change.
Defining constants
const Pi = 3.14159265358979
const MaxSize = 1000
const Greeting = "Hello, World!"
Constants are defined at the top level, outside functions.
Using constants
const Pi = 3.14159265358979
fn circle_area(r:f64 -- area:f64) {
-> r // bind parameter
r dup * Pi *
}
fn circle_circumference(r:f64 -- c:f64) {
-> r // bind parameter
2.0 r * Pi *
}
fn main() {
5.0 circle_area print nl // 78.5398...
5.0 circle_circumference print nl // 31.4159...
}
Constant types
Constants can be any basic type:
// Integer constants
const MaxRetries = 3
const BufferSize = 4096
const InvalidId = -1
// Float constants
const Pi = 3.14159265358979
const E = 2.71828182845905
const Epsilon = 0.00001
// String constants
const Version = "1.0.0"
const AppName = "MyApp"
Constants vs variables
| Feature | Constant | Variable |
|---|---|---|
| Defined at | Top level | Inside functions |
| Can change | No | Yes |
| Scope | Global | Function |
| Syntax | const Name = value |
value -> name |
Built-in constants
| Constant | Value | Type | Description |
|---|---|---|---|
true |
1 | i64 | Boolean true |
false |
0 | i64 | Boolean false |
Ok |
1 | i64 | Success result |
Err |
0 | i64 | Error result |
null |
0 | ptr | Null pointer |
Use null for pointer fields in structs:
struct Node {
value:i64
next:*Node
}
Node { value = 1 next = null } -> a
a @next null == if { "end of list" print nl }
Naming convention
Use PascalCase for constants:
const MaxConnections = 100
const DefaultTimeout = 30
const ApiBaseUrl = "https://api.example.com"
Constants for configuration
const DebugMode = 1
const LogLevel = 2
const MaxThreads = 8
fn main() {
DebugMode if {
"Debug mode enabled" print nl
}
LogLevel 2 >= if {
"Verbose logging" print nl
}
}
Constants for magic numbers
Replace magic numbers with named constants:
Before (unclear)
fn is_valid_port(port:i64 -- valid:i64) {
-> port // bind parameter
port 0 > port 65535 <= and
}
After (clear)
const MinPort = 1
const MaxPort = 65535
fn is_valid_port(port:i64 -- valid:i64) {
-> port // bind parameter
port MinPort >= port MaxPort <= and
}
Constants for error codes
const ErrNone = 0
const ErrNotFound = 1
const ErrPermission = 2
const ErrTimeout = 3
fn handle_error(code:i64 -- ) {
-> code
code switch {
0 { "Success" print nl }
1 { "Not found" print nl }
2 { "Permission denied" print nl }
3 { "Timeout" print nl }
_ { "Unknown error" print nl }
}
}
!!! note "Constants in switch"
Constants cannot currently be used as switch case values. Use literal values instead.
Constants for bit flags
const FlagRead = 1
const FlagWrite = 2
const FlagExecute = 4
fn has_read(flags:i64 -- result:i64) {
-> flags // bind parameter
flags FlagRead and 0 !=
}
fn has_write(flags:i64 -- result:i64) {
-> flags // bind parameter
flags FlagWrite and 0 !=
}
fn main() {
FlagRead FlagWrite or -> permissions
permissions has_read print nl // 1
permissions has_write print nl // 1
}
Computed constants
Constants must be literal values. For computed values, use functions:
const HoursPerDay = 24
const DaysPerWeek = 7
fn hours_per_week( -- h:i64) {
HoursPerDay DaysPerWeek *
}
fn main() {
hours_per_week print nl // 168
}
Module constants
Constants can be accessed from other modules:
// config/config.qd
pub const AppVersion = "2.0.0"
pub const MaxUsers = 1000
// main.qd
use config
fn main() {
"Version: " print config::AppVersion print nl
}
Enums
Enums define a set of named integer constants under a common scope. Values auto-increment from 0, or can be set explicitly.
enum Color {
Red // 0
Green // 1
Blue // 2
}
enum HttpStatus {
Ok = 200
NotFound = 404
ServerError = 500
}
Using enums
Enum values are accessed with EnumName::Variant and are regular i64 values:
enum Direction {
Up
Down
Left
Right
}
fn describe(d:i64 -- ) {
-> dir
dir switch {
Direction::Up { "up" print nl }
Direction::Down { "down" print nl }
Direction::Left { "left" print nl }
Direction::Right { "right" print nl }
_ { "unknown" print nl }
}
}
fn main() {
Direction::Up describe // up
Direction::Left describe // left
// Enums are i64 — arithmetic and comparison work
Direction::Up Direction::Down == if {
"same" print nl
} else {
"different" print nl
}
}
Explicit values
Variants auto-increment from the previous value. Explicit values reset the counter:
enum Token {
Int // 0
Float // 1
Str = 10 // 10
Ident // 11
Plus = 20 // 20
Minus // 21
Eof = -1 // -1
}
Public enums
Use pub enum to export from a module:
// status.qd
pub enum Status {
Ok
Error = -1
Pending = 100
}
What's next?
Learn about Error Handling to write robust code.