Quick Start
Get up and running with Zenoscript in just a few minutes! This guide will walk you through creating your first Zenoscript program.
Create a New Project
Start by creating a new Zenoscript project:
bash
mkdir hello-zenoscript && cd hello-zenoscript
zeno initThis creates a basic project with:
typescript
// index.zs - Notice the clean syntax!
const greet = (name: string) => { `Hello, ${name}!` }
const main = () => {
console.log greet("World") // Optional parentheses
greet("World") |> console.log // Using pipe operator
}
main()Key features shown:
- Automatic returns: Functions return their last expression
- Optional parentheses: Clean function calls without parentheses
- Pipe operations: Chain function calls elegantly
Run Your Program
bash
# Development mode with hot reloading
bun dev
# Or compile and run
bun build index.zs --outdir dist
bun dist/index.jsYour First Zenoscript Program
Let's explore the basic features by building a simple user management system:
typescript
// user.zs
struct User {
id: number;
name: string;
email: string;
status: UserStatus;
}
// Using atoms for type-safe constants
let :active = Symbol.for("active")
let :inactive = Symbol.for("inactive")
let :pending = Symbol.for("pending")
// Create some users
let users = [
{ id: 1, name: "Alice", email: "alice@example.com", status: :active },
{ id: 2, name: "Bob", email: "bob@example.com", status: :inactive },
{ id: 3, name: "Charlie", email: "charlie@example.com", status: :pending }
]
// Filter active users using pipe operations and optional parentheses
let activeUsers = users
|> filter(user => user.status === :active)
|> map(user => user.name)
console.log "Active users:", activeUsers // Optional parentheses
// Pattern matching with automatic return
let getStatusMessage = (status) => match status {
:active => "User is active"
:inactive => "User is inactive"
:pending => "User registration pending"
_ => "Unknown status"
}
// Display status for each user - showcasing clean syntax
users |> forEach(user => {
let message = getStatusMessage user.status // Optional parentheses
console.log `${user.name}: ${message}` // Optional parentheses
})
// Functions with automatic return
let isActiveUser = (user) => { user.status === :active }
let getUserName = (user) => { user.name }
let formatUserInfo = (user) => {
let status = getStatusMessage user.status
let activity = isActiveUser(user) ? "✓" : "✗"
`${activity} ${user.name} (${status})` // Automatically returned
}Key Concepts Demonstrated
1. Optional Parentheses
Clean, readable function calls:
typescript
console.log "Hello" // vs console.log("Hello")
processValue 42 // vs processValue(42)
validateInput userData // vs validateInput(userData)2. Automatic Returns
Functions return their last expression:
typescript
let add = (a, b) => { a + b } // No return needed
let greet = (name) => {
let message = `Hello, ${name}!`
message // Automatically returned
}3. Structs
Define structured data types:
typescript
struct User {
id: number;
name: string;
email: string;
}4. Atoms
Type-safe constants using the : syntax:
typescript
let status = :active // Creates Symbol.for("active")3. Pipe Operations
Chain operations for readable data flow:
typescript
let result = data
|> filter(predicate)
|> map(transform)
|> sort4. Pattern Matching
Powerful control flow with destructuring:
typescript
let message = match status {
:success => "It worked!"
:error => "Something went wrong"
_ => "Unknown result"
}Compiling to TypeScript
When you run your Zenoscript code, it compiles to clean TypeScript:
typescript
// Compiled output
type User = {
id: number;
name: string;
email: string;
status: symbol;
};
const active = Symbol.for("active");
const inactive = Symbol.for("inactive");
const pending = Symbol.for("pending");
const users = [
{ id: 1, name: "Alice", email: "alice@example.com", status: active },
{ id: 2, name: "Bob", email: "bob@example.com", status: inactive },
{ id: 3, name: "Charlie", email: "charlie@example.com", status: pending }
];
const activeUsers = users
.filter(user => user.status === active)
.map(user => user.name);
// ... rest compiles similarlyWorking with Existing TypeScript
Zenoscript works seamlessly with existing TypeScript libraries:
typescript
// Import any TypeScript/JavaScript library
import express from "express"
import { readFile } from "fs/promises"
// Use TypeScript types
let app = express()
// Zenoscript syntax with TypeScript interop
let handler = (req, res) => {
let response = match req.method {
"GET" => handleGet(req)
"POST" => handlePost(req)
_ => { status: 405, message: "Method not allowed" }
}
res.json(response)
}
app.use("/api", handler)Interactive Development
Use the REPL for experimentation:
bash
zeno replzs> let x = 42
→ const x = 42;
zs> x |> double |> toString
→ x.double().toString()
zs> match :success { :success => "Yes!" }
→ (() => {
const __match_value = Symbol.for("success");
if (__match_value === Symbol.for("success")) {
return "Yes!";
}
})()Next Steps
Now that you've got the basics down:
- Learn about Language Syntax in detail
- Explore Pattern Matching capabilities
- Check out Examples for real-world usage
- Set up your development environment with the CLI tools
Need Help?
- Check the Language Guide for detailed syntax reference
- Browse Examples for inspiration
- Join our community on Discord