Examples
Here are practical examples to help you get started with Logos. Each example demonstrates different features of the language.
Todo CLI App
A command-line todo list manager with persistent storage:
todo_app.lgs
// todo_app.lgs - Command-line todo manager
let todoFile = "todos.json"
let todos = []
let loadTodos = fn() {
if !fileExists(todoFile) {
return []
}
let res = fileRead(todoFile)
if !res.ok {
return []
}
let parsed = parseJson(res.value)
if parsed == null {
return []
}
return parsed
}
let saveTodos = fn() {
let json = toJson(todos)
let res = fileWrite(todoFile, json)
return res.ok
}
let listTodos = fn() {
if len(todos) == 0 {
print(colorYellow(" No todos yet!"))
return null
}
let i = 0
for i < len(todos) {
let todo = todos[i]
let status = ""
if todo["done"] {
status = colorGreen("[x]")
} else {
status = colorYellow("[ ]")
}
print(" " + toStr(i + 1) + ". " + status + " " + todo["task"])
i = i + 1
}
}
let addTodo = fn(task) {
let todo = table{
"task": task,
"done": false,
"created": dateTimeStr(),
}
todos = push(todos, todo)
saveTodos()
print(colorGreen("Added: " + task))
}
let completeTodo = fn(index) {
if index < 1 || index > len(todos) {
print(colorRed("Invalid todo number"))
return null
}
let todo = todos[index - 1]
todo["done"] = true
todos[index - 1] = todo
saveTodos()
print(colorGreen("Completed: " + todo["task"]))
}
// Main loop
print(colorBold(colorCyan("Todo App")))
todos = loadTodos()
print(colorGreen("Loaded " + toStr(len(todos)) + " todo(s)"))
let running = true
for running {
let input = trim(prompt(colorBold("todo> ")))
let parts = split(input, " ")
let cmd = lower(parts[0])
if cmd == "quit" || cmd == "q" {
running = false
}
if cmd == "list" || cmd == "ls" {
listTodos()
}
if cmd == "add" {
if len(parts) < 2 {
print(colorRed("Usage: add <task>"))
} else {
let task = join(slice(parts, 1, len(parts)), " ")
addTodo(task)
}
}
if cmd == "done" {
if len(parts) < 2 {
print(colorRed("Usage: done <number>"))
} else {
completeTodo(toInt(parts[1]))
}
}
}
print(colorYellow("Goodbye!"))HTTP API Client
Fetch data from a REST API with proper error handling:
http_client.lgs
// http_client.lgs - Fetch and display API data
let fetchUsers = fn() {
let res = httpGet("https://jsonplaceholder.typicode.com/users")
if !res.ok {
print(colorRed("Error: " + res.error))
return []
}
// HTTP responses have body and status in value
let users = parseJson(res.value.body)
return users
}
let displayUser = fn(user) {
print("---")
print("Name: " + user["name"])
print("Email: " + user["email"])
print("Company: " + user["company"]["name"])
}
// Fetch and display users
print(colorCyan("Fetching users from API..."))
print("")
let users = fetchUsers()
if len(users) > 0 {
for user in users {
displayUser(user)
}
print("---")
print(colorGreen("Total users: " + toStr(len(users))))
}JSON Configuration Manager
Load and manage JSON configuration files:
json_config.lgs
// json_config.lgs - Configuration file manager
let loadConfig = fn(path) {
let res = fileRead(path)
if !res.ok {
return null
}
let parsed = parseJson(res.value)
if parsed == null {
print(colorRed("Error: invalid JSON in " + path))
return null
}
return parsed
}
let saveConfig = fn(path, config) {
let json = toJson(config)
let res = fileWrite(path, json)
return res.ok
}
let getConfigValue = fn(config, key, defaultValue) {
if config == null {
return defaultValue
}
if !has(config, key) {
return defaultValue
}
return config[key]
}
// Load or create default config
let configPath = "config.json"
let config = null
if fileExists(configPath) {
config = loadConfig(configPath)
print(colorGreen("Loaded config from: " + configPath))
} else {
print(colorYellow("Creating default config..."))
config = table{
"app": table{
"name": "MyApp",
"version": "1.0.0",
"debug": false,
},
"server": table{
"host": "localhost",
"port": 8080,
},
}
saveConfig(configPath, config)
}
// Access config values with defaults
let appName = getConfigValue(config["app"], "name", "Unknown")
let port = getConfigValue(config["server"], "port", 3000)
print("Application: " + appName)
print("Port: " + toStr(port))File Search Utility
Search for files by name pattern with optional content search:
file_search.lgs
// file_search.lgs - Search files by pattern
let searchFiles = fn(dir, pattern, searchText) {
let results = []
let dirRes = fileReadDir(dir)
if !dirRes.ok {
return results
}
for entry in dirRes.value {
let path = dir + "/" + entry
// Check if filename matches pattern
if contains(lower(entry), lower(pattern)) {
if len(searchText) == 0 {
// Just matching filename
results = push(results, table{
"path": path,
"match": "filename",
})
} else {
// Also search file contents
let fileRes = fileRead(path)
if fileRes.ok {
let lines = split(fileRes.value, "\n")
let lineNum = 1
for line in lines {
if contains(lower(line), lower(searchText)) {
results = push(results, table{
"path": path,
"line": lineNum,
"match": trim(line),
})
}
lineNum = lineNum + 1
}
}
}
}
}
return results
}
// Search for .lgs files containing "fn"
let dir = "."
let pattern = ".lgs"
let searchText = "fn"
print(colorYellow("Searching for '" + pattern + "' files containing '" + searchText + "'..."))
print("")
let results = searchFiles(dir, pattern, searchText)
if len(results) == 0 {
print(colorYellow("No matches found"))
} else {
print(colorBold("Found " + toStr(len(results)) + " match(es):"))
for result in results {
if has(result, "line") {
print(colorGreen(" " + result["path"]) + ":" + toStr(result["line"]))
print(" " + result["match"])
} else {
print(colorGreen(" " + result["path"]))
}
}
}Concurrent Processing
Process items concurrently using spawn:
concurrent.lgs
// concurrent.lgs - Parallel processing example
use "std/math"
let processItem = fn(item) {
// Simulate some computation
let result = mathFactorial(item)
print("Processed " + toStr(item) + "! = " + toStr(result))
return result
}
let items = [5, 6, 7, 8, 9, 10]
print("Processing items concurrently...")
print("")
// Process all items in parallel using spawn for
spawn for item in items {
processItem(item)
}
print("")
print("All items queued for processing!")
// You can also spawn individual blocks
spawn {
sleep(100)
print("This runs in the background")
}Testing Example
Write tests using the testing standard library:
test_math.lgs
// test_math.lgs - Example test file
use "std/testing"
use "std/math"
let add = fn(a, b) -> a + b
let multiply = fn(a, b) -> a * b
suite("arithmetic", fn() {
assert("add positive", add(2, 3), 5)
assert("add negative", add(-1, 1), 0)
assert("add zero", add(0, 0), 0)
assert("multiply", multiply(3, 4), 12)
assert("multiply by zero", multiply(5, 0), 0)
})
suite("math stdlib", fn() {
assert("factorial 5", mathFactorial(5), 120)
assert("factorial 0", mathFactorial(0), 1)
assert("fib 10", mathFib(10), 55)
assert("isPrime 17", mathIsPrime(17), true)
assert("isPrime 4", mathIsPrime(4), false)
assert("gcd", mathGcd(48, 18), 6)
})
summary()
// Run with: lgs test_math.lgs
// Output:
// ok arithmetic, math stdlib 11 tests passedFizzBuzz
The classic FizzBuzz problem:
fizzbuzz.lgs
// fizzbuzz.lgs - Classic FizzBuzz
let fizzbuzz = fn(n) {
let i = 1
for i <= n {
if i % 15 == 0 {
print("FizzBuzz")
} else if i % 3 == 0 {
print("Fizz")
} else if i % 5 == 0 {
print("Buzz")
} else {
print(toStr(i))
}
i = i + 1
}
}
fizzbuzz(30)CLI Tool with Arguments
Build command-line tools that accept arguments:
greet.lgs
// greet.lgs - CLI tool example
let cliArgs = args()
// First arg is the script name, skip it
if len(cliArgs) < 2 {
print("Usage: lgs greet.lgs <name> [--loud]")
exit(1)
}
let name = cliArgs[1]
let loud = false
// Check for flags
let i = 2
for i < len(cliArgs) {
if cliArgs[i] == "--loud" {
loud = true
}
i = i + 1
}
let greeting = "Hello, " + name + "!"
if loud {
print(colorBold(upper(greeting)))
} else {
print(greeting)
}
// Usage:
// lgs greet.lgs World -> Hello, World!
// lgs greet.lgs World --loud -> HELLO, WORLD!More Examples
Find more examples in the GitHub repository, including:
- Backup script with file operations
- Cron job scheduler
- Movie file organizer
- Line counter utility
- Guessing game
