Language Basics
Variables, control flow, functions, and data types
Equana is a language designed for scientific computing. It uses 1-based indexing, multiple dispatch, and a clean syntax that reads like math notation.
This tutorial covers the core syntax you need to start writing Equana code. Every code block below is interactive — edit it and run it to experiment.
Variables & Assignment
Variables are created by assigning a value with =. No declaration keyword is needed — just pick a name and assign:
x = 42
name = "Alice"
pi_approx = 3.14159
println(x)
println(name)
println(pi_approx)Variables are dynamically typed — you can reassign to a different type at any time:
x = 10
println(x)
x = "now a string"
println(x)Numbers
Equana has two primary numeric types: Int64 (integers) and Float64 (floating-point numbers). Arithmetic works as you'd expect:
# Integer arithmetic
a = 10 + 3
b = 10 - 3
c = 10 * 3
d = 10 / 3
e = 10 % 3
f = 2 ^ 10
println(a)
println(b)
println(c)
println(d)
println(e)
println(f)Special numeric values are available:
println(Inf)
println(-Inf)
println(NaN)
println(1.0 / 0.0)
println(0.0 / 0.0)The nothing value represents the absence of a value:
x = nothing
println(x)
println(x == nothing)Booleans & Comparisons
Boolean values are true and false. Comparison operators return booleans:
# Comparison operators
println(3 > 2)
println(3 < 2)
println(3 == 3)
println(3 != 4)
println(3 >= 3)
println(3 <= 2)Logical operators combine boolean values:
# Logical AND, OR, NOT
println(true && false)
println(true || false)
println(!true)
# Combining comparisons
x = 15
println(x > 10 && x < 20)Strings
Create strings with double quotes. Use ${} for interpolation and + for concatenation:
greeting = "Hello"
name = "World"
# Concatenation
println(greeting + ", " + name + "!")
# String interpolation
age = 28
println("${name} is ${age} years old")
println("2 + 2 = ${2+2}")For more on strings — template literals, escape sequences, and string functions — see the Working with Strings tutorial.
Arrays
Arrays use square brackets with comma-separated values. Indexing is 1-based (the first element is at index 1):
arr = [10, 20, 30, 40, 50]
# Access elements (1-based)
println(arr[1])
println(arr[3])
# Length
println(length(arr))Numeric arrays are backed by typed memory (NDArrays) — you can update elements in place:
arr = [1, 2, 3]
arr[2] = 99
println(arr)Non-numeric arrays (like strings) are growable — use push to append:
fruits = ["apple", "banana"]
push(fruits, "cherry")
println(fruits)Slicing
Use ranges to extract sub-arrays:
arr = [10, 20, 30, 40, 50]
# Slice from index 2 to 4
println(arr[2:4])
# Every other element
println(arr[1:2:5])Tuples
Tuples are fixed-size collections that can hold mixed types. Create them with parentheses:
t = (1, "hello", 3.14)
# Access by index (1-based)
println(t[1])
println(t[2])
println(t[3])
println(length(t))Destructure tuples into individual variables:
point = (3.0, 4.0)
(x, y) = point
println(x)
println(y)Ranges
Ranges represent sequences of numbers. The syntax is start:stop or start:step:stop:
# Basic range
r = 1:5
println(r)
println(length(r))
# Range with step
r2 = 0:2:10
println(r2)
# Check if a value is in a range
println(includes(1:10, 5))
println(includes(1:10, 15))Ranges are commonly used for iteration and array slicing (shown in later sections).
Control Flow
if / elseif / else
Conditional branching uses if, elseif, and else, terminated with end:
x = 15
if x > 20
println("large")
elseif x > 10
println("medium")
else
println("small")
endfor Loops
Iterate over ranges, arrays, or any collection with for ... in:
# Loop over a range
for i in 1:5
println(i)
end# Loop over an array
fruits = ["apple", "banana", "cherry"]
for fruit in fruits
println("I like ${fruit}")
endUse enumerate to get both the index and value:
colors = ["red", "green", "blue"]
for pair in enumerate(colors)
(i, color) = pair
println("${i}: ${color}")
endbreak & continue
break exits a loop early. continue skips to the next iteration:
# Find the first multiple of 7
for i in 1:100
if i % 7 == 0
println("First multiple of 7: ${i}")
break
end
end# Print only odd numbers
for i in 1:10
if i % 2 == 0
continue
end
println(i)
endswitch / case
Pattern match on values with switch:
day = 3
switch day
case 1
println("Monday")
case 2
println("Tuesday")
case 3
println("Wednesday")
default
println("Another day")
endCases can match multiple values:
x = 6
switch x % 3
case 0
println("divisible by 3")
case 1, 2
println("not divisible by 3")
endtry / catch
Handle errors gracefully with try and catch:
try
x = 1 / 0
println(x)
catch e
println("Error: " + e.message)
endFunctions
Named Functions
Functions use function r = name(params) ... end syntax. The return value is assigned to the return variable (r by convention):
function r = square(x)
r = x * x
end
function r = greet(name)
r = "Hello, ${name}!"
end
println(square(5))
println(greet("Alice"))Functions can return multiple values using tuple syntax:
function (q, r) = divmod(a, b)
q = int64(a / b)
r = a % b
end
(quotient, remainder) = divmod(17, 5)
println("17 / 5 = ${quotient} remainder ${remainder}")Arrow Functions
Arrow functions provide a concise syntax for short functions:
double = x -> x * 2
add = (a, b) -> a + b
println(double(21))
println(add(3, 4))Arrow functions with multi-line bodies use begin ... end:
classify = x -> begin
if x > 0
"positive"
elseif x < 0
"negative"
else
"zero"
end
end
println(classify(5))
println(classify(-3))
println(classify(0))Higher-Order Functions
Pass functions as arguments to map, filter, and reduce:
arr = [1, 2, 3, 4, 5]
# Square each element
println(map(arr, x -> x ^ 2))
# Keep only even numbers
println(filter(arr, x -> x % 2 == 0))
# Sum all elements
println(reduce(arr, (a, b) -> a + b, 0))Comments & Block Syntax
Single-line comments start with #:
# This is a comment
x = 42 # inline comment
println(x)Blocks are terminated with end — this applies to functions, if, for, switch, and try:
function r = add(a, b)
r = a + b
end
println(add(1, 2))Syntax Conveniences
Equana has a few optional syntax features that make numerical code more concise. These are all optional — you can always use the conventional forms — but they can make code more expressive.
Bracket-Free Function Calls
Any known function can be called without parentheses — just write the function name followed by its argument:
# These are equivalent:
println(sqrt(16.0))
println sqrt(16.0)
# Calls chain right-to-left:
# sin cos 0.0 means sin(cos(0.0))
println(sin(cos(0.0)))Implicit Multiplication
A numeric literal followed by a variable or expression is treated as multiplication — no * needed:
x = 5
println(2 x)
println(3 x ^ 2)
pi_approx = 3.14159
r = 10.0
println(2 pi_approx * r)Method Syntax
Any function can be called as a method on its first argument using dot notation:
function r = double(x)
r = x * 2
end
# Standard call
println(double(5))
# Method syntax — same result
println(5.double())Useful Built-in Functions
Here's a quick reference of commonly used built-in functions:
# Math
println(sqrt(16.0))
println(abs(-5))
println(min(3, 7))
println(max(3, 7))# Arrays
arr = [3, 1, 4, 1, 5, 9]
println(sort(arr))
println(reverse(arr))
println(sum(arr))
println(min(arr))
println(max(arr))# Type inspection
println(typeof(42))
println(typeof(3.14))
println(typeof("hello"))
println(typeof(true))
println(typeof(nothing))Summary
Quick Reference
| Concept | Syntax |
|---|---|
| Assignment | x = 42 |
| String interpolation | "value is ${x}" |
| Array | [1, 2, 3] |
| Tuple | (1, "a", 3.0) |
| Range | 1:10 or 1:2:10 |
| if/else | if cond ... else ... end |
| for loop | for i in 1:10 ... end |
| switch | switch val ... case 1 ... default ... end |
| Named function | function r = f(x) ... r = x * 2 ... end |
| Arrow function | f = x -> x * 2 |
| Bracket-free call | sin x instead of sin(x) |
| Implicit multiply | 2x instead of 2 * x |
| Method syntax | x.double() instead of double(x) |
| Comment | # comment |
What's Next
- Types & Multiple Dispatch — Define structs, abstract types, typed functions, and operator overloading
- Working with Strings — Deep dive into string manipulation and formatting