A Tour of Kiwi
This page walks through Kiwi from top to bottom. Each section links to the page that covers the topic in full. You can paste any example into a file and run it with kiwi file.kiwi, or try it line by line in the REPL.
Printing
Section titled “Printing”println prints a value followed by a newline; print leaves the newline off. Parentheses are optional.
print "Hello, "println "World!"println("Parentheses work too.")Variables
Section titled “Variables”Assign to a name to create a variable. There is no declaration keyword, and a variable can hold any type.
name = "Kiwi"version = 1pi = 3.14159active = truenothing = null
a, b, c = 10, 20, 30println "${a}, ${b}, ${c}" # 10, 20, 30const declares a value that can’t be reassigned. Constant names are upper case.
const MAX_RETRIES = 3See Variables.
| Type | Examples |
|---|---|
integer | 42, -7, 0xFF, 0b1010 |
float | 3.14, -0.5, 1.5e3 |
boolean | true, false |
string | "hello", 'raw' |
list | [1, 2, 3] |
hashmap | {name: "Alice", age: 30} |
null | null |
typeof names a value’s type:
println typeof(42) # integerprintln typeof("hello") # stringprintln typeof([1, 2]) # listprintln typeof({}) # hashmapKiwi also has date, bytes, lambda, generator and struct instances. See Types.
Strings
Section titled “Strings”Strings interpolate any expression inside ${...}. Single-quoted strings are raw: backslashes are kept as written, which suits regular expressions and Windows paths.
name = "world"println "Hello, ${name}!" # Hello, world!println "2 + 2 = ${2 + 2}" # 2 + 2 = 4println "${name.size()} characters" # 5 characters
pattern = '\d+'println "a1b22".scan(pattern) # ["1", "22"]Strings come with a set of built-in methods:
s = " Hello, Kiwi! "println s.trim() # Hello, Kiwi!println s.uppercase() # HELLO, KIWI!println s.contains("Kiwi") # trueprintln s.trim().split(", ") # ["Hello", "Kiwi!"]println "-" * 10 # ----------See Strings.
Numbers
Section titled “Numbers”println 10 + 3 # 13println 10 - 3 # 7println 10 * 3 # 30println 10 / 4 # 2.5 (/ always produces a float)println 10 // 4 # 2 (floor division)println 10 % 3 # 1println 2 ** 10 # 1024?? picks the right-hand side when the left is null:
value = nullprintln value ?? "default" # defaultSee Operators.
Making decisions
Section titled “Making decisions”score = 85
if score >= 90 println "A"elsif score >= 80 println "B"else println "Keep going"endcase is an expression. It can test conditions or compare one value against several:
hour = 14
part_of_day = case when hour < 12 "morning" when hour < 17 "afternoon" else "evening"endprintln "Good ${part_of_day}!" # Good afternoon!
day = "Saturday"mood = case day when "Monday" "Here we go again." when "Saturday", "Sunday" "Weekend!" else "Just another day."endprintln mood # Weekend!A when guard makes return, throw, break, next and exit conditional, which keeps early exits on one line:
fn safe_divide(a, b) throw "Cannot divide by zero" when b == 0 return a / bend
println safe_divide(9, 3) # 3See Control Flow.
fruits = ["kiwi", "mango", "lime"]
for fruit in fruits do println fruitend
for fruit, i in fruits do println "${i + 1}. ${fruit}"end
for n in [1 to 20] do next when n % 2 == 0 break when n > 7 print "${n} "endprintln "" # 1 3 5 7
repeat 3 as i do println "Step ${i}" # Step 1, Step 2, Step 3end
count = 0while count < 3 do count += 1endSee Loops.
Lists are ordered and can hold values of any type. Indexing starts at 0.
colors = ["red", "green", "blue"]println colors[0] # redprintln colors.size() # 3
colors.push("yellow")colors.remove("green")println colors # ["red", "blue", "yellow"]println colors[0:2] # ["red", "blue"][a to b] builds a range, and list methods take lambdas:
total = [1 to 20] .filter(do (n) => n % 3 == 0) .map(do (n) => n * n) .sum()
println total # 819See Lists.
Hashmaps
Section titled “Hashmaps”person = { name: "Alice", age: 28, city: "Portland"}
println person["name"] # Aliceprintln person.age # 28
person["email"] = "alice@example.com"person.remove("city")println person.keys() # ["name", "age", "email"]println person.get("phone", "n/a") # n/a
for key, value in person do println "${key}: ${value}"endSee Hashmaps.
Functions
Section titled “Functions”A function returns the value of its last expression, so return is only needed to leave early.
fn add(a, b) a + bend
fn greet(name = "stranger", greeting = "Hello") "${greeting}, ${name}!"end
println add(3, 4) # 7println greet() # Hello, stranger!println greet("Bob", greeting: "Hi") # Hi, Bob!Functions can take a variable number of arguments, and *list spreads a list into arguments:
fn sum(*numbers) numbers.sum()end
println sum(1, 2, 3) # 6println sum(*[4, 5, 6]) # 15See Functions.
Lambdas
Section titled “Lambdas”do (params) => expression creates a lambda. For more than one expression, drop the arrow and close with end.
square = do (n) => n * nprintln square(5) # 25
describe = do (n) if n > 0 "positive" else "not positive" endendprintln describe(-3) # not positiveLambdas close over the variables around them:
fn make_counter() count = 0 do () count += 1 count endend
next_id = make_counter()next_id()println next_id() # 2See Lambdas.
Errors
Section titled “Errors”fn divide(a, b) throw error::ValueError("b must not be zero") when b == 0 a / bend
try divide(1, 0)catch e println "${e["error"]}: ${e["message"]}" # ValueError: b must not be zerofinally println "done"endSee Error Handling.
Structs
Section titled “Structs”Structs bundle data with behavior. @name is an instance variable and new is the constructor.
struct Animal fn new(name) @name = name end
fn speak() "${@name} makes a sound." endend
struct Dog < Animal fn speak() "${@name} barks!" endend
println Animal.new("Generic").speak() # Generic makes a sound.println Dog.new("Rex").speak() # Rex barks!See Structs.
Packages
Section titled “Packages”A package groups functions under a name. Call them with ::.
package geometry fn area(w, h) w * h endend
println geometry::area(3, 4) # 12Your own files load with import "path/to/file". See Packages.
The standard library
Section titled “The standard library”The standard library is loaded automatically; there is nothing to import.
println math::sqrt(144.0) # 12println string::titleize("the quick fox") # The Quick Foxprintln json::stringify({a: 1}) # {"a":1}println time::now().year() >= 2024 # truecontent = fio::read("notes.txt")response = http::get("https://example.com")rows = csv::parse(fio::read("data.csv"))Browse the Standard Library for the full list of packages.