🦀 🔗 @ Operator Chaining in Rust

Rust Documentation

🔗 @ Operator Chaining in Rust

TuskLang supports elegant chaining of @ operators in Rust, allowing you to compose complex operations in a readable, fluent manner with zero-cost abstractions.

Basic Chaining

// Simple property chaining
let user_city = @user.address.city;

// Method chaining let formatted = @string.trim().to_lowercase().replace(" ", "-");

// Mixed chaining let result = @query("SELECT * FROM users").first().name.to_uppercase();

Null-Safe Chaining

// Safe navigation operator
let city = @user?.address?.city;

// With fallback let city = @user?.address?.city.unwrap_or("Unknown");

// Multiple levels let manager_email = @employee?.department?.manager?.email.unwrap_or("no-manager@example.com");

// Array access let first_tag = @post?.tags?.get(0)?.name;

Collection Chaining

// Vector operations
let result = @users
    .iter()
    .filter(|u| u.active)
    .map(|u| &u.email)
    .collect::<std::collections::HashSet<_>>()
    .into_iter()
    .collect::<Vec<_>>()
    .sort();

// More complex example let top_customers = @orders .iter() .group_by(|o| o.customer_id) .map(|(customer_id, orders)| { CustomerSummary { id: customer_id, total: orders.iter().map(|o| o.total).sum(), count: orders.len(), } }) .sorted_by(|a, b| b.total.partial_cmp(&a.total).unwrap()) .take(10) .collect::<Vec<_>>();

// With conditions let active_premium_users = @users .iter() .filter(|u| u.status == "active") .filter(|u| u.subscription == "premium") .sorted_by(|a, b| b.created_at.cmp(&a.created_at)) .collect::<Vec<_>>();

Query Builder Chaining

// Database query chaining
let users = @db.table("users")
    .select(vec!["id", "name", "email"])
    .where("active", true)
    .where("created_at", ">", @last_week)
    .where_in("role", vec!["admin", "editor"])
    .order_by("name")
    .limit(50)
    .get();

// With joins let orders = @db.table("orders") .join("users", "orders.user_id", "users.id") .join("products", "orders.product_id", "products.id") .select(vec![ "orders.*", "users.name as customer_name", "products.name as product_name" ]) .where("orders.status", "completed") .where_between("orders.created_at", @start_date, @end_date) .get();

Transform Chains

// String transformations
let slug = @title
    .trim()
    .to_lowercase()
    .chars()
    .map(|c| if c.is_alphanumeric() { c } else { '-' })
    .collect::<String>()
    .trim_matches('-')
    .to_string();

// Date transformations let formatted_date = @user.created_at .format("%Y-%m-%d") .to_string() .replace("-", "/");

// Number formatting let price_display = format!("${:.2}", @product.price) .replace(".", ",");

Conditional Chaining

// Chain with conditions
let query = @db.table("products")
    .when(@category.is_some(), |q| q.where("category_id", @category.unwrap()))
    .when(@min_price.is_some(), |q| q.where("price", ">=", @min_price.unwrap()))
    .when(@search.is_some(), |q| q.where("name", "like", &format!("%{}%", @search.unwrap())))
    .when(@sort == "price", |q| q.order_by("price", @direction))
    .get();

// Conditional method calls let result = @data .if(@should_filter, |d| d.iter().filter(|x| x.active).collect()) .if(@should_sort, |d| d.iter().sorted().collect()) .if(@limit.is_some(), |d| d.iter().take(@limit.unwrap()).collect());

Pipeline Chaining

// Unix-style pipeline
let result = @input
    .pipe(|s| s.trim())
    .pipe(|s| s.split(','))
    .pipe(|v| v.iter().map(|s| s.parse::<i32>().unwrap()).collect::<Vec<_>>())
    .pipe(|v| v.iter().filter(|&&x| x > 0).collect::<Vec<_>>())
    .pipe(|v| v.iter().sum::<i32>());

// With custom functions fn process_text(text: &str) -> Vec<String> { text .pipe(|s| normalize_whitespace(s)) .pipe(|s| remove_punctuation(s)) .pipe(|s| tokenize(s)) .pipe(|v| remove_stopwords(v)) .pipe(|v| stem(v)) }

// Data processing pipeline let report = @raw_data .pipe(|d| validate(d)) .pipe(|d| clean(d)) .pipe(|d| transform(d)) .pipe(|d| aggregate(d)) .pipe(|d| format(d));

Async Chain Operations

// Async/await chaining
let result = @fetch(url)
    .await?
    .json::<serde_json::Value>()
    .await?
    .pipe(|data| process(data))
    .pipe(|processed| save(processed))
    .await?;

// Parallel operations let results = futures::future::join_all(vec![ @fetch_user_data(id), @fetch_user_posts(id), @fetch_user_stats(id) ]).await;

let (user, posts, stats) = match results.as_slice() { [user, posts, stats] => (user, posts, stats), _ => return Err("Failed to fetch user data"), };

Cache Chaining

// Cache with chaining
let user = @cache
    .remember(&format!("user:{}", @id), Duration::from_secs(3600))
    .get(|| @db.table("users").find(@id))
    .with(vec!["posts", "comments"])
    .append(|u| {
        let mut user = u.clone();
        user.calculated_field = @calculate_something();
        user
    });

// Tagged cache chaining @cache .tags(vec!["users", &format!("user:{}", @id)]) .put(&format!("user_profile:{}", @id), @profile, Duration::from_secs(3600));

Validation Chaining

// Input validation chains
let validation = @validator
    .input(@request.all())
    .rules(ValidationRules {
        name: "required|string|max:255",
        email: "required|email|unique:users",
        age: "required|integer|min:18",
    })
    .validate()
    .on_fail(|errors| @response.json(errors, 422))
    .on_pass(|data| @create_user(data));

HTTP Client Chaining

// HTTP request building
let response = @http
    .post("https://api.example.com/users")
    .headers({
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert("Authorization", format!("Bearer {}", @token).parse().unwrap());
        headers.insert("Content-Type", "application/json".parse().unwrap());
        headers
    })
    .timeout(Duration::from_secs(5))
    .retry(3)
    .body(serde_json::json!({
        "name": @name,
        "email": @email,
    }))
    .send()
    .await?;

// Response handling let data = @response .ensure_success()? .json::<serde_json::Value>() .await? .get("data") .unwrap() .as_array() .unwrap() .iter() .map(|item| transform(item)) .collect::<Vec<_>>();

Form Builder Chaining

// Form building
let form = @form("user")
    .method("POST")
    .action("/users")
    .field("name")
        .field_type("text")
        .required()
        .placeholder("Enter name")
    .field("email")
        .field_type("email")
        .required()
        .placeholder("Enter email")
    .field("age")
        .field_type("number")
        .min(18)
        .max(120)
    .submit("Create User");

Iterator Chaining

// Complex iterator chains
let processed_data = @raw_data
    .iter()
    .filter(|item| item.is_valid())
    .map(|item| item.transform())
    .filter_map(|item| item.ok())
    .take_while(|item| item.priority > 0)
    .collect::<Vec<_>>();

// Parallel iterator chains let results = @data .par_iter() .map(|item| process_item(item)) .filter(|result| result.is_success()) .collect::<Vec<_>>();

Error Handling Chains

// Result chaining
let result = @operation()
    .and_then(|data| process_data(data))
    .and_then(|processed| validate_data(processed))
    .and_then(|valid| save_data(valid))
    .map_err(|error| {
        @log("Error in chain: {}", error);
        error
    });

// Option chaining let user_email = @user .and_then(|u| u.profile) .and_then(|p| p.contact) .and_then(|c| c.email) .unwrap_or("no-email@example.com");

Database Transaction Chaining

// Transaction chains
let result = @db.transaction(|tx| {
    tx.table("users")
        .insert(@user_data)
        .and_then(|user_id| {
            tx.table("profiles")
                .insert(ProfileData {
                    user_id,
                    bio: @bio,
                })
        })
        .and_then(|profile_id| {
            tx.table("preferences")
                .insert(PreferenceData {
                    user_id,
                    theme: @theme,
                })
        })
        .commit()
});

File System Chaining

// File operations chaining
let content = @file
    .read("data.txt")
    .and_then(|content| content.parse::<String>())
    .and_then(|content| content.lines().collect::<Vec<_>>())
    .and_then(|lines| lines.iter().filter(|line| !line.is_empty()).collect::<Vec<_>>())
    .and_then(|lines| lines.join("\n"))
    .unwrap_or_else(|_| "Default content".to_string());

Configuration Chaining

// Configuration building
let config = @config
    .load("app.tusk")
    .and_then(|cfg| cfg.merge(@env_config))
    .and_then(|cfg| cfg.validate())
    .and_then(|cfg| cfg.resolve_placeholders())
    .unwrap_or_else(|_| @default_config);

Best Practices

1. Use Meaningful Variable Names

// Good
let active_users = @users.iter().filter(|u| u.active).collect::<Vec<_>>();

// Better let active_users = @users .iter() .filter(|user| user.is_active()) .collect::<Vec<_>>();

2. Break Long Chains

// Break long chains for readability
let processed_users = @users
    .iter()
    .filter(|user| user.is_active())
    .collect::<Vec<_>>();

let user_emails = processed_users .iter() .map(|user| &user.email) .collect::<Vec<_>>();

3. Handle Errors Gracefully

// Use Result chaining for error handling
let result = @operation()
    .and_then(|data| process(data))
    .map_err(|error| {
        @log("Operation failed: {}", error);
        error
    });

4. Use Type Annotations

// Explicit type annotations for clarity
let users: Vec<User> = @db
    .table("users")
    .where("active", true)
    .get();

5. Leverage Rust's Type System

// Use Rust's type system for safety
let user_ids: Vec<u32> = @users
    .iter()
    .map(|user| user.id)
    .collect();

Performance Considerations

1. Lazy Evaluation

// Use iterators for lazy evaluation
let expensive_operation = @data
    .iter()
    .filter(|item| item.is_expensive())
    .map(|item| item.process())
    .collect::<Vec<_>>();

2. Parallel Processing

// Use parallel iterators for CPU-intensive tasks
use rayon::prelude::*;

let results = @data .par_iter() .map(|item| process_item(item)) .collect::<Vec<_>>();

3. Memory Efficiency

// Use references to avoid cloning
let user_names: Vec<&str> = @users
    .iter()
    .map(|user| user.name.as_str())
    .collect();

The @ operator chaining in Rust provides a powerful, type-safe way to compose complex operations while maintaining Rust's performance characteristics and memory safety guarantees.