Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Built-in types

Goblin values have runtime types; variables do not need type annotations. An operation succeeds only when its value types are compatible.

TypeExamplesNotes
Integer0, -42Signed whole number
Float3.14, -0.5Floating-point number
Booltrue, falseLogical value
NilnilAbsence of a value; it prints as nil
String"hello"Immutable Unicode text
BytesBytes("data")Immutable raw byte sequence
List[1, "two"]Ordered, mutable collection
Dict{"name": "Ada"}Mutable key/value collection
ChanChan(0)Channel for concurrent functions
GoblinGoblin(func() {})Handle to a function running concurrently
Functionfunc() {}Callable value

Custom types are covered in Types and methods.

Numbers

Integer literals have no decimal point; float literals do. Arithmetic preserves an integer result when both operands are integers. If either operand is a float, the result is a float. Integer division truncates its fractional part. The % operator returns the remainder after truncating division; the result has the dividend's sign and is a float if either operand is a float.

print(7 / 2)     # 3
print(7 / 2.0)   # 3.5
print(2 + 0.5)   # 2.5
print(-3 * 4)    # -12
print(-7 % 3)    # -1
print(7.5 % 2)   # 1.5

Numbers can be compared across integer and float values. Division or modulo by zero raises ZeroDivisionError. Int() and Float() convert numbers, booleans, and numeric strings; converting a float to Int removes its fractional portion.

print(Int("42"))   # 42
print(Int(3.9))     # 3
print(Float(true))  # 1
print(max(3, 5, 4))

When to convert and when to calculate

Use Int() or Float() at the edge of a program, where a value arrives as text or where an integer operation must become floating-point. Keep calculations in their natural numeric form after that. For example, parse a configuration value once, then use min() and max() to keep it within a permitted range.

var requested_workers = Int("12")
var workers = min(max(requested_workers, 1), 8)
print(workers) # 8

Int() rejects non-numeric text with ValueError. This makes it suitable for validating numeric input inside a try/catch block.

Booleans and nil

Use Bool(value) to convert any value by truthiness. False, nil, numeric zero, and empty strings, lists, dictionaries, or bytes are false.

print(Bool(""))       # false
print(Bool([1]))      # true
print(!nil)           # true
print(true && false)  # false

A function with no explicit result returns nil. Comparing any value against nil with == is safe — it is true only for nil itself — but arithmetic and indexing on nil are errors.

Using truthiness for optional values

Truthiness is convenient for choosing a fallback or guarding an optional collection. Use an explicit comparison with nil when zero, false, or an empty collection must still be treated as a present value.

var nickname = ""
print(nickname || "anonymous") # anonymous

var limit = 0
if limit == nil {
    print("no limit supplied")
}

Strings and bytes

Strings are immutable Unicode text. They can be iterated by character, combined with +, and repeated with *, but they are not indexable with []. Use index() or last_index() to find a character position. See Strings for conversions and typical methods.

Bytes are immutable raw byte sequences. Bytes("ABC") has size 3 and its first element is the integer 65. Common byte methods mirror string operations: decode(), contains(), has_prefix(), split(), replace(), and trim(). Use Bytes for raw data and strings for text.

Working with bytes

Use Bytes when reading or sending binary-oriented data, or when indexing must produce numeric byte values. Use decode() when that data should become text.

var header = Bytes("GET")
print(header[0])          # 71
print(header.contains("E"))
print(header.decode())    # GET

Lists and dictionaries

Lists and dictionaries are mutable collections. A list is ordered and uses integer indexes; a dictionary maps keys to values. Empty collections are false in conditions. See Collections for creation, indexing, and method guides.

Channels

Chan(capacity) creates a channel. Send with send(), receive with recv(), and close with close(). Capacity 0 creates an unbuffered channel. Use spawn() to start a concurrent function.

var done = Chan(0)
spawn(func() {
    done.send("finished")
})
print(done.recv())
done.close()

Coordinating concurrent work

An unbuffered channel makes send() wait until another function calls recv(). This makes it useful for returning one result from spawned work. A buffered channel can accept up to its capacity before a receiver is ready.

var results = Chan(2)
spawn(func() { results.send(2 * 2) })
spawn(func() { results.send(3 * 3) })
print(results.recv() + results.recv())
results.close()

Close a channel only when no more values will be sent. Receiving from a closed, drained channel raises ValueError, rather than producing a special nil value.

Goblin handles

Goblin(function, args...) starts the function in a new goroutine and returns a handle. wait() joins it: the function's result is returned, an error it raised is re-raised, and the outcome is cached across repeated calls. done() reports completion without blocking, and wait(timeout = seconds) raises TimeoutError when the function outlives the timeout.

func square(value) {
    return value * value
}

var worker = Goblin(square, 6)
print(worker.wait()) # 36

See Concurrency for how handles, channels, and spawn fit together.

Common operations

TypeCommon constructors and operations
Integer / FloatInt(value), Float(value), max(...), min(...)
Bool / NilBool(value), !value, value && other, value || other
StringStr(value), size, contains(), split(), replace()
BytesBytes(value), size, decode(), contains(), split()
ListList(value), size, first, last, push(), pop(), sort(), copy()
DictDict(), get(), set_default(), keys(), items(), update()
ChanChan(size), send(value), recv(), close()
GoblinGoblin(function, args...), wait(), done()
FunctionFunction(value), value(...)

Use value.attributes() in the REPL to inspect all operations provided by a runtime value. Constructible values also expose value.constructor; see Built-in functions.