FluentAI Language Guide
This guide covers the core language features of FluentAI. By the end, you'll understand how to write idiomatic FluentAI code.
Variables & Types
FluentAI is a statically-typed language with type inference. Variables are immutable by default, promoting functional programming practices.
Variable Declaration
// Immutable variable (default)
let name = "Alice";
// name = "Bob"; // Error! Cannot reassign
// Mutable variable
let mut counter = 0;
counter := counter + 1; // OK, using assignment operator
// Type annotations (optional with inference)
let age: int = 30;
let price: float = 19.99;
let active: bool = true;
Statement Termination
FluentAI follows C#/.NET conventions for semicolons. Statements require semicolons, but the last expression in a block doesn't need one as it serves as the block's return value:
// Statements require semicolons
let x = 10;
let y = 20;
$(x + y).print();
// Last expression in block - no semicolon needed
let result = {
let a = 5;
let b = 10;
a + b // This is the block's return value
};
// Control flow blocks don't need semicolons after closing braces
if (condition) {
doSomething();
} else {
doSomethingElse();
} // No semicolon after the closing brace
Constants
Constants are compile-time values that never change:
const PI = 3.14159;
const MAX_CONNECTIONS = 100;
const API_URL = "https://api.fluentai.dev";
Built-in Types
| Type | Description | Example |
|---|---|---|
int |
Integer numbers | 42, -10, 0 |
float |
Floating-point numbers | 3.14, -0.5 |
string |
Text strings | "hello", f"Hi {name}" |
bool |
Boolean values | true, false |
List<T> |
Dynamic arrays | [1, 2, 3] |
Map<K, V> |
Key-value pairs | {"a": 1, "b": 2} |
Set<T> |
Unique values | #{1, 2, 3} |
String Interpolation
let name = "Alice";
let age = 30;
// F-strings for interpolation
let message = f"Hello, {name}! You are {age} years old.";
let calculation = f"Next year you'll be {age + 1}.";
Functions
Functions are first-class citizens in FluentAI, supporting both traditional and lambda syntax.
Function Declaration
// Basic function
private function add(a: int, b: int) -> int {
a + b // Implicit return
}
// With explicit return
public function factorial(n: int) -> int {
if (n <= 1) {
return 1;
}
n * factorial(n - 1)
}
// Generic function
private function identity(value: T) -> T {
value
}
Lambda Expressions
Lambdas provide concise syntax for anonymous functions:
// Single parameter
let double = (x) => x * 2;
// Multiple parameters
let add = (a, b) => a + b;
// With type annotations
let divide = (a: float, b: float) => a / b;
// Block body
let complex = (x) => {
let temp = x * 2;
temp + 10
};
Higher-Order Functions
// Functions as parameters
private function apply_twice(f: (T) -> T, value: T) -> T {
f(f(value))
}
let result = apply_twice((x) => x * 2, 5); // 20
// Functions returning functions
private function make_adder(n: int) -> (int) -> int {
(x) => x + n
}
let add5 = make_adder(5);
let result = add5(10); // 15
Pattern Matching
Pattern matching is one of FluentAI's most powerful features, enabling elegant control flow.
Basic Pattern Matching
// Matching on enums
result.match()
.case(Ok(value), => process(value))
.case(Err(error), => handle_error(error))
.get();
// Matching with values
status_code.match()
.case(200, => "Success")
.case(404, => "Not Found")
.case(500, => "Server Error")
.default(=> "Unknown")
.get();
Destructuring Patterns
// Struct destructuring
user.match()
.case({name, age, email}, => {
$(f"User: {name}, {age} years old").print();
send_email(email)
})
.get();
// List patterns
list.match()
.case([], => "Empty list")
.case([x], => f"Single element: {x}")
.case([first, ...rest], => f"First: {first}, rest: {rest}")
.get();
Pattern Guards
// Guards add conditions to patterns
person.match()
.case({age}, => age >= 65, => "Senior")
.case({age}, => age >= 18, => "Adult")
.case({age}, => "Minor")
.get();
Method Chaining
Method chaining is fundamental to FluentAI's design, enabling readable data pipelines.
Collection Operations
// Chaining transformations
let result = users
.filter(user => user.active)
.map(user => user.score)
.filter(score => score > 80)
.fold(0, (sum, score) => sum + score);
// Complex pipeline
orders
.filter(order => order.status == "completed")
.map(order => order.items)
.flatten()
.group_by(item => item.category)
.map_values(items => items.len())
.sort_by_value()
.take(10);
Optional Chaining
// Safe navigation with ?
let email = user.profile?.contact?.email;
// Chaining with optionals
config
.get("database")?
.get("connection")?
.get("timeout")
.unwrap_or(30);
Modules
Modules provide organization and encapsulation for your code.
Module Definition
// In user_service.fc
public struct User {
id: Uuid,
pub name: string,
email: string // private by default
}
public function create_user(name: string, email: string) -> User {
User {
id: Uuid.new(),
name: name,
email: email
}
}
private function validate_email(email: string) -> bool {
email.contains("@")
}
Using Modules
// Import entire module
use my_app::user_service;
let user = user_service.create_user("Alice", "alice@example.com");
// Import specific items
use my_app::user_service::{User, create_user};
// Import with alias
use my_app::database::connection as db;
Effect System
FluentAI's effect system provides controlled side effects with compile-time guarantees.
Performing Effects
// I/O effects
perform IO.print("Starting process...");
let content = perform IO.read_file("data.txt");
perform IO.write_file("output.txt", processed_data);
// State effects
perform State.set("counter", 0);
let count = perform State.get("counter");
perform State.update("counter", (n) => n + 1);
// Time effects
let now = perform Time.now();
perform Time.sleep(1000); // milliseconds
Effect Handlers
// Custom effect handling
handle {
let data = process_with_logging();
save_results(data)
} with {
Log.debug(msg) => if (DEBUG) { console.log(f"[DEBUG] {msg}") },
Log.info(msg) => console.log(f"[INFO] {msg}"),
Log.error(msg) => console.error(f"[ERROR] {msg}")
}
// Mocking effects for testing
handle {
let user = fetch_user_from_api(id);
assert_eq(user.name, "Test User")
} with {
Http.get(url) => Ok({name: "Test User", id: 123})
}
Error Handling
FluentAI uses Result types and pattern matching for robust error handling.
Result Type
// Functions that can fail return Result
private function divide(a: float, b: float) -> Result {
if (b == 0) {
Err("Division by zero")
} else {
Ok(a / b)
}
}
// Chaining with Result
divide(10, 2)
.map(x => x * 2)
.and_then(x => divide(x, 3))
.unwrap_or(0);
Error Propagation
// Using ? for early return
private function calculate(input: string) -> Result {
let parsed = parse_float(input)?; // Returns early if Err
let validated = validate_range(parsed)?;
let result = complex_calculation(validated)?;
Ok(result)
}
// Combining multiple Results
let total = result1
.and_then(|v1| result2.map(|v2| v1 + v2))
.or_else(|_| Ok(default_value));
Traits
Traits define shared behavior that types can implement.
Defining Traits
public trait Drawable {
private function draw(self) -> unit;
private function get_bounds(self) -> Rectangle;
}
public trait Serializable {
private function to_json(self) -> string;
private function from_json(json: string) -> Result;
}
Implementing Traits
public struct Circle {
center: Point,
radius: float
}
private Circle as Drawable {
private function draw(self) -> unit {
// Drawing implementation
perform Graphics.draw_circle(self.center, self.radius);
}
private function get_bounds(self) -> Rectangle {
Rectangle {
x: self.center.x - self.radius,
y: self.center.y - self.radius,
width: self.radius * 2,
height: self.radius * 2
}
}
}