Skip to content

Collections & Strings

Lists, maps, and Strings each speak two coexisting dialects for the operations they share. A natural-language phrasing reads like English — add x to l, size of l, sorted l, uppercase of s — and a method phrasing calls receiver.method(args). Both compile to exactly the same runtime; reach for whichever reads better at the call site. The switch below flips every example on this page between the two.

A method resolves by the receiver's static type — the compiler knows a List<Integer> from a Map<String, V> from a String and offers only that type's methods, checking argument types and arity at compile time. Operations split into two shapes:

  • Pure / query forms return a value and never touch the receiver — sorted l / l.sorted(), size of m / m.size, uppercase of s / s.upper(). Use them anywhere an expression is allowed.
  • Mutating forms change the receiver in place and are written as bare statements — add x to l / l.add(x), clear l / l.clear(). They have no result, so they cannot appear inside an expression.

The richer transforms (.filtered, .mapped, .joined, .get_or, …) have no natural-language spelling and stay in method form — they are listed in the reference tables below.

Dialect

Accessors

The size and endpoint accessors read a collection without changing it:

Natural languageMethod / propertyOnReturns
size of cc.sizelist, map, StringInteger
first of ll.firstlistOptional<T>
last of ll.lastlistOptional<T>
keys of mm.keysmapList<K>
values of mm.valuesmapList<V>
length of ss.lengthStringInteger
c.is_emptylist, mapBoolean
Peek at a listaccessors.sw
swoftlang
command "accessors" {
    execute {
        set nums to [10, 20, 30]
        send "size ${size of nums}, empty ${nums.is_empty}" to sender
        send "first ${first of nums otherwise 0}, last ${last of nums otherwise 0}" to sender
    }
}

Lists

Mutating a list

The four in-place edits with a natural spelling:

Natural languageMethodEffect
add x to ll.add(x)append x
remove x from ll.remove(x)remove the first occurrence of x
clear ll.clear()remove everything
Build up a listlist-mut.sw
swoftlang
command "list-mut" {
    execute {
        set nums to [3, 1, 2]
        add 4 to nums
        remove 1 from nums
        add 9 to nums
        send "size ${size of nums}" to sender
    }
}

The remaining mutators are method-only: l.add_all(other) appends every element of another list, l.remove_at(i) drops the element at an index, and l.insert(i, x) splices x in at position i.

Querying & transforming

Membership, sorting, and reversal each have a natural form; the rest are method-only:

Natural languageMethodReturns
l contains xl.contains(x)Boolean
sorted ll.sorted()List<T>
sorted l by <fn>l.sorted_by(fn)List<T>
reversed ll.reversed()List<T>
Sort and searchlist-query.sw
swoftlang
command "list-query" {
    execute {
        set nums to [3, 1, 2]

        if nums contains 3 {
            send "has 3" to sender
        }
        set up to sorted nums
        set ranked to sorted nums by function(n: Integer) { return 0 - n }
        set down to reversed nums
        send "sorted ${up.size}, ranked ${ranked.size}, reversed ${down.size}" to sender
    }
}

These further transforms are method-only — each returns a new value and leaves the receiver alone:

MethodReturnsNotes
.index_of(x)Optional<Integer>position of x, or none
.get(i)Optional<T>element at index i, or none
.count(x)Integerhow many times x occurs
.joined(sep)Stringjoin elements with sep
.sorted_by_desc(key)List<T>by a key(elem) lambda, descending
.shuffled()List<T>randomly shuffled copy
.filtered(pred)List<T>elements where pred(elem) is true
.mapped(fn)List<U>fn(elem) over every element
.taken(n)List<T>first n elements
.dropped(n)List<T>all but the first n
.min_by(key)Optional<T>element with the smallest key
.max_by(key)Optional<T>element with the largest key

The lambda methods take the element type; .filtered needs a Boolean lambda, .sorted_by / .min_by / .max_by a comparable (number or String) key, and .mapped may return any type, which becomes the new list's element type.

swoftlang
command "list-methods" {
    execute {
        set nums to [3, 1, 2]

        set idx to nums.index_of(2) otherwise 0 - 1
        set joined to nums.joined(", ")
        set evens to nums.filtered(function(n: Integer) { return n % 2 == 0 })
        set doubled to nums.mapped(function(n: Integer) { return n * 2 })
        set top to nums.max_by(function(n: Integer) { return n }) otherwise 0
        set some to nums.taken(2)
        send "idx ${idx}, joined ${joined}, top ${top}" to sender
        send "evens ${evens.size}, doubled ${doubled.size}, some ${some.size}" to sender
    }
}

Maps

The full set of map operations — reads, writes, membership, keys of / values of, deletion, and clear — is covered in both dialects on the Maps page. Beyond those, maps carry method-only helpers. Reads return an Optional<V> because the key may be absent — narrow with exists or supply an otherwise; .get_or(k, default) bakes the fallback in and returns a plain V.

MethodReturnsNotes
.get_or(k, default)Vvalue for k, else default
.put_all(other)copy every entry of another map
.sorted_by_key()Map<K, V>new map, ordered by key ascending
.sorted_by_key_desc()Map<K, V>ordered by key descending
.sorted_by_value()Map<K, V>ordered by value ascending
.sorted_by_value_desc()Map<K, V>ordered by value descending
.sorted_by(key)Map<K, V>ordered by a key(k, v) lambda, ascending
swoftlang
command "map-methods" {
    execute {
        set scores to { "alice": 10, "bob": 7 }
        scores.put_all({ "dan": 1 })

        set safe to scores.get_or("zoe", 0)
        set byval to scores.sorted_by_value_desc()
        set bykey to scores.sorted_by(function(k: String, v: Integer) { return v })
        send "safe ${safe}, keys ${keys of scores}, values ${values of scores}" to sender
        send "byval ${byval.size}, bykey ${bykey.size}" to sender
    }
}

Strings

Strings are immutable, so every String operation is a pure expression that returns a new String, list, or scalar. Case conversion and length carry a natural spelling:

Natural languageMethodReturns
uppercase of ss.upper()String
lowercase of ss.lower()String
length of ss.length()Integer
Normalise a stringstrings.sw
swoftlang
command "strings" {
    execute {
        set greeting to "  Hello, World  "
        set clean to greeting.trimmed()
        set up to uppercase of clean
        send "clean '${up}' len ${length of clean}" to sender
    }
}

Everything else is method-only:

MethodReturnsNotes
.trimmed()Stringstrip leading/trailing whitespace
.contains(s)Booleansubstring test
.starts_with(s)Booleanprefix test
.ends_with(s)Booleansuffix test
.replace(from, to)Stringreplace every from with to
.split(sep)List<String>split on sep
.substring(start, end)Stringcharacters [start, end)
.index_of(s)Optional<Integer>position of s, or none
.repeated(n)Stringthe String repeated n times
.reversed()Stringcharacters reversed
.padded_left(n, pad)Stringleft-pad to width n with pad
.padded_right(n, pad)Stringright-pad to width n with pad
.first_chars(n)Stringfirst n characters (clamped)
.last_chars(n)Stringlast n characters (clamped)
swoftlang
command "string-methods" {
    execute {
        set clean to "Hello, World"
        set parts to clean.split(", ")
        set rep to "ab".repeated(3)
        set starts to clean.starts_with("Hello")
        send "parts ${parts.size}, rep ${rep}, starts ${starts}" to sender
    }
}