Logos / Docs

Syntax & Types

This page covers the complete syntax of Logos. The language is designed to be minimal and expressive, with a focus on readability.

Variables

Variables are declared using the let keyword. Logos is dynamically typed, so you don't need to specify types.

// strings
let name = "uthman"

// numbers (integers and floats)
let age = 20
let score = 3.14

// booleans
let active = true

// null
let nothing = null

Functions

Functions are first-class values in Logos. Define them with the fn keyword.

// regular function
let greet = fn(name) {
    return "hello " + name
}

// call it
print(greet("world"))

Arrow Functions

For simple functions, use the arrow syntax:

// single expression - implicit return
let double = fn(x) -> x * 2
let add = fn(x, y) -> x + y

// use them
print(toStr(double(5)))    // 10
print(toStr(add(2, 3)))    // 5

Control Flow

If / Else

let age = 20

if age > 18 {
    print("adult")
} else {
    print("minor")
}

// can also chain
if age < 13 {
    print("child")
} else if age < 20 {
    print("teenager")
} else {
    print("adult")
}

For Loops

// while-style loop
let i = 0
for i < 5 {
    print(toStr(i))
    i += 1
}

For-In Loops

// iterate over arrays
let nums = [1, 2, 3, 4, 5]
for n in nums {
    print(toStr(n))
}

Arrays

Arrays are ordered collections of values.

let fruits = ["apple", "banana", "mango"]

// access by index (0-based)
let first = fruits[0]
print(first)  // apple

// arrays can hold mixed types
let mixed = [1, "hello", true, null]

Tables (Hashmaps)

Tables are key-value collections, similar to objects or dictionaries.

let user = table{
    "name": "uthman",
    "age": 20,
    "active": true,
}

// access values
print(user["name"])  // uthman

// nested tables
let data = table{
    "user": table{
        "name": "uthman",
        "role": "admin",
    },
}

Switch

Switch statements for multi-way branching:

let role = "admin"

switch role {
    case "admin" { print("full access") }
    case "user"  { print("limited access") }
    default      { print("no access") }
}

Spawn (Concurrency)

Run code concurrently using spawn blocks:

// spawn a single block
spawn {
    print("running concurrently")
}

// spawn a loop
let items = [1, 2, 3, 4, 5]
spawn for item in items {
    print(toStr(item))
}

HTTP

Make HTTP requests with built-in functions:

let res = httpGet("https://api.example.com/data")

if res.ok {
    print(res.value.body)
} else {
    print("request failed")
}

File I/O

Read and write files:

// read a file
let file = fileRead("data.txt")
if file.ok {
    print(file.value)
}

// write to a file
fileWrite("output.txt", "Hello, World!")

JSON

Parse and work with JSON:

let json = parseJson("{"name": "uthman", "age": 20}")
print(json["name"])  // uthman

Modules

Import standard library modules:

use "std/math"
use "std/array"
use "std/string"

print(toStr(mathFactorial(5)))   // 120
print(toStr(arraySum([1, 2, 3])))  // 6
print(strReverse("hello"))       // olleh

Closures

Functions capture their surrounding scope:

let makeCounter = fn() {
    let count = 0
    return fn() {
        count += 1
        return count
    }
}

let counter = makeCounter()
print(toStr(counter()))  // 1
print(toStr(counter()))  // 2
print(toStr(counter()))  // 3

Recursion

Functions can call themselves:

let fib = fn(n) {
    if n <= 1 { return n }
    return fib(n - 1) + fib(n - 2)
}

print(toStr(fib(10)))  // 55