Tulpar vs Rust
Rust and Tulpar both compile ahead-of-time to native binaries with no VM or
GC pause, and both land in the same performance class. The trade-off is
memory model versus batteries: Rust’s ownership/borrow checker buys memory
safety without a garbage collector, but its standard library ships no HTTP
server, no SQLite bindings, and no ORM — those come from crates like
actix-web, sqlx, and diesel. Tulpar has no borrow checker, but wings
and orm are already part of the runtime.
JSON vs Struct Usage
Section titled “JSON vs Struct Usage”struct User { name: String, age: u32,}
fn main() { let user = User { name: "Hamza".to_string(), age: 27 };
println!("{}", user.name); println!("{}", user.age);}Arrays and Loops
Section titled “Arrays and Loops”fn main() { let numbers = [1, 2, 3, 4, 5];
for n in numbers.iter() { println!("Item: {}", n); }}String Processing
Section titled “String Processing”fn main() { let input = " TULPAR LANG ";
let cleaned = input.trim().to_lowercase(); let parts: Vec<&str> = cleaned.split(' ').collect();
println!("Cleaned: {}", cleaned); println!("First word: {}", parts[0]);}HTTP API in One File
Section titled “HTTP API in One File”Rust has no standard-library HTTP server, so even a minimal API reaches for
a crate like actix-web plus serde for JSON — and SQLite, an ORM, and
OpenAPI docs are each further crates (sqlx/diesel, utoipa, …) on top
of that. Tulpar’s wings and orm ship in the compiler’s own runtime.
import "wings";import "orm";
orm_open("app.db");define_model("users", { "id": "INTEGER PRIMARY KEY AUTOINCREMENT", "name": "TEXT NOT NULL", "age": "INTEGER"});
func list_users(req) { return ok(orm_all("users")); }func create_user(req) { return created(orm_create("users", req.json)); }
get("/users", "list_users");post("/users", "create_user");body_schema({"name": "str", "age?": "int"}); // invalid body → 422, automatically
serve(8080); // + Swagger UI, /openapi.json, /metrics, /healthzuse actix_web::{get, web, App, HttpServer, HttpResponse};use serde::{Deserialize, Serialize};use std::sync::Mutex;
#[derive(Serialize, Deserialize, Clone)]struct User { id: u32, name: String, age: u32,}
#[get("/users")]async fn list_users(users: web::Data<Mutex<Vec<User>>>) -> HttpResponse { HttpResponse::Ok().json(&*users.lock().unwrap())}
#[actix_web::main]async fn main() -> std::io::Result<()> { let users = web::Data::new(Mutex::new(Vec::<User>::new()));
HttpServer::new(move || App::new().app_data(users.clone()).service(list_users)) .bind(("0.0.0.0", 8080))? .run() .await // SQLite/ORM (sqlx or diesel), OpenAPI (utoipa), and /metrics // (actix-web-prom) are all separate crates layered on top of this.}See Wings Tutorial for the guided, three-app version of the Tulpar side, and Benchmarks for how the two compare on raw HTTP throughput.