-
-
Notifications
You must be signed in to change notification settings - Fork 0
Sets Maps And Sequences
Arrays preserve position, maps associate keys with values, and sets represent membership without duplicates. Choosing among them is a semantic decision: the type should state what observations a caller is allowed to depend on.
let queue = ["compile", "test", "publish"]
let ports = mapOf([("http", 80), ("https", 443)])
let capabilities = #{"read", "write", "read"}
queue keeps all three positions. ports associates each key with a value. capabilities
contains two distinct members; repeated input does not create repeated membership.
A set is written #{...}. The literal evaluates every written member in source order and
constructs the set afterwards, so duplicate members collapse only after their expressions have run
— writing the same expression twice never removes an effect or changes the order in which a failure
is reported. setOf remains available and builds the same value from an array.
let ranks = #{3, 1, 2, 1} // #{1, 2, 3}
let none: Set[Str] = #{}
Iteration and rendering are key-ordered, not insertion-ordered, because the value is the same ordered set the standard library has always used.
An empty Set literal needs type context because it has no member from which to infer T. Maps have
no dedicated literal; Map.empty and Set.empty provide generic constructors when the context
belongs at the call site.
import Std.Map as Map
import Std.Set as Set
let names: Set[Str] = Set.empty()
let counts: Map[Str, Int] = Map.empty()
candidate in container answers whether a set contains a value. It occupies comparison precedence,
so it groups the way == does and does not need parentheses in a condition.
import Std.Set as Set
if "publish" in granted { deploy() }
let unknown = Set.filter(&names, fn(name: Str) -> Bool => !(name in known))
The candidate is evaluated before the container, and the operator performs one lookup in the ordered set. It does not iterate, and it does not call user code.
in is deliberately set-only for now. Extending it to strings, arrays, maps, ranges, and
program types raises questions about borrowing and about cost that are better settled together than
one container at a time; until they are, Str.contains, Array.contains, and
Std.Map.containsKey say the same thing without pretending to a general protocol.
Set code is clearest when written in the vocabulary of membership and algebra.
import Std.Set as Set
fn mayDeploy(granted: Set[Str]) -> Bool {
let required = setOf(["build", "publish"])
Set.isSubsetOf(&required, &granted)
}
The standard set module includes isEmpty, equals, intersects, subset and superset tests,
bulk insertion and removal, filtering, mapping, union, intersection, difference, and symmetric
difference. isSupersetOf(left, right) is defined as isSubsetOf(right, left), preserving one
source of truth for the relation.
Prefer contains or a set predicate to a hand-written loop with an early Boolean flag. The direct
operation records intent and lets the implementation select the appropriate representation.
A map iteration yields (K, V), so the relationship between a key and its value remains explicit.
fn total(scores: Map[Str, Int]) -> Int {
var out = 0
for (_, score) in scores { out = out + score }
out
}
Use get when absence is ordinary and pattern-match its Option result. Use the module's
transformation and partition operations when producing another map; converting to parallel key
and value arrays creates an index relationship that the type no longer protects.
Arrays are the appropriate result when position or sorted order is observable. The Std.List
module supplies transformation, folding, searching, slicing, grouping, zipping, and sorting
operations over arrays. Methods cover the small built-in core; module functions carry the broader
algorithm vocabulary.
Std.Iter separates a source from its consumption. map, filter, take, drop, zip, and
related adapters construct sequence descriptions; consumers such as collection or folding request
elements through Sequence.advance.
This distinction matters when a pipeline can stop early. An eager intermediate array performs all upstream work and retains all intermediate values. A lazy sequence asks only for the elements the consumer reaches.
The interpreter stores built-in maps and sets in balanced trees ordered by the runtime's value
comparison. size reads the structure's stored count, contains and keyed lookup descend the tree,
and iteration yields ascending key order. Standard-library modules written in Pudu may still build
larger operations from these primitives, so complexity claims belong to the named operation rather
than to the word “collection” in general.
- Modules And Imports
- Values, Bindings, And Blocks
- Types And Inference
- Records, Sums, And Tuples
- Functions Generics And Traits
- Pattern Language
- Control Flow And Patterns
- Iteration And Loops
- Failure And Propagation
- Numbers And Collections
- Sets Maps And Sequences
- Keyed Structures
- Trees And Hierarchies
- Standard Library
- Output Formatting And Testing
- Tasks And Scopes
- Compile-Time Evaluation
- Typed Macros
- References And Unsafe
- Worked Programs