Comments
Comments are essential for documenting your code. Good comments explain why code exists, not just what it does. Oxide's comment syntax is identical to Rust's, which will be familiar if you've used C, C++, Java, or JavaScript.
Line Comments
The most common comment form is the line comment, which starts with // and continues to the end of the line:
fn main() {
// This is a line comment
let x = 5 // This comment follows code
// Comments can span
// multiple lines
// like this
let y = 10
}
Use line comments liberally to explain non-obvious logic:
fn calculateDiscount(price: Float, memberYears: Int): Float {
// Base discount for all members
var discount = 0.05
// Long-term members get additional rewards
// The formula was approved by marketing in Q3 2024
if memberYears >= 5 {
discount += 0.02 * (memberYears - 4).min(5) as Float
}
price * discount
}
Block Comments
For longer explanations, use block comments that start with /* and end with */:
fn main() {
/* This is a block comment.
It can span multiple lines
and is useful for longer explanations. */
let x = 5
/*
* Some developers prefer to format
* block comments with asterisks
* on each line for readability.
*/
}
Block comments can also be nested, which is useful when commenting out code that already contains comments:
fn main() {
/*
This outer comment contains:
/* An inner comment */
And continues after it.
*/
println!("Hello!")
}
In practice, line comments (//) are more commonly used than block comments.
Documentation Comments
Oxide supports special documentation comments that can be processed by documentation tools. These come in two forms.
Outer Documentation Comments (///)
Use /// to document the item that follows (functions, structs, enums, etc.):
/// Calculates the factorial of a non-negative integer.
///
/// # Arguments
///
/// * `n` - The number to calculate factorial for
///
/// # Returns
///
/// The factorial of `n`, or `null` if `n` is negative
///
/// # Examples
///
/// ```oxide
/// let result = factorial(5)
/// assert_eq!(result, Some(120))
/// ```
public fn factorial(n: Int): Int? {
if n < 0 {
return null
}
if n <= 1 {
return Some(1)
}
Some(n * factorial(n - 1)??)
}
Documentation comments support Markdown formatting, so you can include:
- Headers with
# - Code blocks with triple backticks
- Lists with
*or- - Bold with
**text** - Links with
[text](url)
Inner Documentation Comments (//!)
Use //! at the beginning of a file or module to document the module itself:
//! # String Utilities
//!
//! This module provides helper functions for string manipulation.
//!
//! ## Features
//!
//! - Case conversion
//! - Trimming and padding
//! - Search and replace
//!
//! ## Example
//!
//! ```oxide
//! import mylib.strings
//!
//! let result = strings.toTitleCase("hello world")
//! assert_eq!(result, "Hello World")
//! ```
public fn toTitleCase(s: &str): String {
// Implementation here
s.toString()
}
public fn capitalize(s: &str): String {
// Implementation here
s.toString()
}
Inner documentation comments are typically placed at the very top of a file, before any code.
Common Documentation Sections
By convention, documentation for public APIs follows a standard structure:
/// Brief one-line description of the function.
///
/// More detailed explanation if needed. This can span multiple
/// paragraphs and include any relevant background information.
///
/// # Arguments
///
/// * `param1` - Description of the first parameter
/// * `param2` - Description of the second parameter
///
/// # Returns
///
/// Description of what the function returns.
///
/// # Errors
///
/// Description of when this function returns an error.
///
/// # Panics
///
/// Description of when this function might panic.
///
/// # Safety
///
/// For unsafe functions, describe safety requirements.
///
/// # Examples
///
/// ```oxide
/// let result = myFunction(arg1, arg2)
/// ```
public fn myFunction(param1: Int, param2: &str): Result<String, Error> {
// Implementation
}
Not all sections are needed for every function. Use the sections that are relevant:
# Arguments- When parameters aren't self-explanatory# Returns- For non-obvious return values# Errors- For functions returningResult# Panics- When the function can panic# Safety- Required forunsafefunctions# Examples- Highly recommended for public APIs
Documenting Structs and Enums
Document each field or variant:
/// Represents a user in the system.
///
/// Users are the primary actors in our application and
/// can perform various actions based on their role.
#[derive(Debug, Clone)]
public struct User {
/// Unique identifier for the user.
id: Int,
/// Display name shown in the UI.
name: String,
/// Email address for notifications.
/// Must be verified before the user can post.
email: String,
/// Whether the user has admin privileges.
isAdmin: Bool,
}
/// Possible states for an order.
public enum OrderStatus {
/// Order has been placed but not yet processed.
Pending,
/// Order is being prepared for shipment.
Processing,
/// Order has been shipped to the customer.
/// Contains the tracking number.
Shipped { trackingNumber: String },
/// Order has been delivered successfully.
Delivered,
/// Order was cancelled.
/// Contains the reason for cancellation.
Cancelled { reason: String },
}
Best Practices
Write Comments for Your Future Self
Code that seems obvious today might be confusing in six months:
// BAD: States what the code does (obvious from reading it)
// Increment counter by 1
counter += 1
// GOOD: Explains why
// We count from 1 because the API expects 1-indexed results
counter += 1
Keep Comments Up to Date
Outdated comments are worse than no comments. When you change code, update the corresponding comments:
// BAD: Comment doesn't match code
// Returns the user's full name
fn getUsername(user: &User): String {
user.email.clone() // Actually returns email!
}
// GOOD: Comment matches code
// Returns the user's email as their display identifier
fn getUsername(user: &User): String {
user.email.clone()
}
Use Comments to Explain "Why", Not "What"
// BAD: Describes what the code does
// Loop through users and filter by active status
let activeUsers = users.iter().filter { it.isActive }
// GOOD: Explains the business reason
// Only active users should receive the weekly newsletter
let activeUsers = users.iter().filter { it.isActive }
Document Public APIs Thoroughly
Internal code can have lighter documentation, but public APIs deserve comprehensive docs:
/// Parses a date string in ISO 8601 format.
///
/// Accepts dates in the format `YYYY-MM-DD`. The time component
/// is optional and defaults to midnight UTC if not provided.
///
/// # Arguments
///
/// * `input` - A string slice containing the date to parse
///
/// # Returns
///
/// A `DateTime` if parsing succeeds, or `null` if the input
/// is not a valid ISO 8601 date string.
///
/// # Examples
///
/// ```oxide
/// let date = parseIsoDate("2024-03-15")
/// assert!(date.isSome())
///
/// let invalid = parseIsoDate("not a date")
/// assert!(invalid.isNone())
/// ```
public fn parseIsoDate(input: &str): DateTime? {
// Implementation
}
Summary
- Use
//for line comments (most common) - Use
/* */for block comments (can be nested) - Use
///to document the following item - Use
//!to document the containing module - Documentation comments support Markdown
- Follow standard sections: Arguments, Returns, Errors, Panics, Examples
- Comment the "why", not the "what"
- Keep comments synchronized with code
Good documentation makes your code more maintainable and helps others (including your future self) understand your intent.