Interval

Inherits from Collection

Interval — An arithmetic sequence of integers.

Intervals represent a range of integers without materialising a list. They are immutable value objects backed by three integers: from, to, step.

Use to: or to:by: on any Integer to create an interval:

1 to: 10            // => (1 to: 10)
1 to: 10 by: 2     // => (1 to: 10 by: 2)
(1 to: 10) size    // => 10

Instance Methods

size source

Number of elements in the interval.

Returns 0 when the step direction does not move from toward to.

Examples

(1 to: 10) size      // => 10
(1 to: 1) size       // => 1
(1 to: 0) size       // => 0
(1 to: 0 by: 2) size  // => 0
do: block source

Iterate over each element, evaluating block with each one.

Examples

(1 to: 3) do: [:i | Transcript show: i]
at: index source

Return the element at the given 1-based index.

Raises index_out_of_bounds for any index outside 1..self size — including on an empty interval. Unlike first/last, at: never raises empty_collection: there is no dedicated "no valid index" case for a keyed accessor, matching Array>>at:'s rule that only a no-argument accessor treats emptiness as its own condition.

Examples

(1 to: 10) at: 1            // => 1
(1 to: 10) at: 10           // => 10
(1 to: 10 by: 2) at: 3      // => 5
first source

First element of the interval.

Raises empty_collection if the interval is empty, matching List first / String first.

Examples

(1 to: 10) first     // => 1
last source

Last element of the interval.

Raises empty_collection if the interval is empty (see first).

Examples

(1 to: 10) last      // => 10
(1 to: 10 by: 3) last  // => 10
asList source

Materialise the interval into a List of its elements (ADR 0095 §6 — the canonical large-collection example (1 to: 100000) asList).

Perf override of Collection>>asList: expands the range natively in a single pass, faster than the generic do:-fold.

Examples

(1 to: 5) asList            // => #(1, 2, 3, 4, 5)
(1 to: 10 by: 3) asList    // => #(1, 4, 7, 10)
(1 to: 0) asList            // => #()
printString source

Return a developer-readable string representation.

Examples

(1 to: 10) printString          // => "(1 to: 10)"
(1 to: 10 by: 2) printString   // => "(1 to: 10 by: 2)"

Inherited Methods

From Collection

size

Return the number of elements.

do: _block

Iterate over each element, evaluating block with each one.

printString

Return a developer-readable string representation.

species

Return the class used to build results from collection operations.

Used by collect:, select:, and reject: to return the same collection type as the receiver. Sealed subclasses override this.

Examples

#(1, 2) species         // => List
#[1, 2] species         // => Array
isEmpty

Test if the collection has no elements.

Examples

#() isEmpty                  // => true
#(1) isEmpty                 // => false
isNotEmpty

Test if the collection has at least one element.

Examples

#(1) isNotEmpty              // => true
#() isNotEmpty               // => false
anyOne

Return any single element of the collection — no ordering guarantee.

Intended for the unordered collections (Set, Bag, Dictionary), which deliberately have no first/last: there is no canonical order to answer from, so this answers some element without promising which one — the answer may differ between calls, and callers must not rely on it being stable. Ordered collections (Array, Interval, List) inherit it too, but should reach for first/last instead when order matters.

Defined once here, not per-subclass: do: already gives every collection a way to grab one element — whichever one do: reaches first, in the receiver's own iteration order. Raises empty_collection if the collection has no elements.

Uses ^ (non-local return) for early exit — compiles to throw/catch on BEAM, the same trick detect:/anySatisfy: use further below.

Examples

(Set new add: 1) anyOne                       // => 1
((Bag new add: 1) anyOne)                      // => 1
(#{#a => 1} anyOne)                             // => 1
includes: element

Test if the collection contains the given element.

Default implementation iterates with do: and returns early on match. Subclasses may override with more efficient lookup.

Compares with equals:, so an element class that overrides it is matched by value rather than by representation (BT-2997). Set overrides this with a sorted-list lookup and so compares with raw =:= instead — keyed containers decide identity in the VM and cannot honour equals:.

Goes through beamtalk_equality:eq/2 rather than sending equals: directly. A bare send would reach Object>>equals: on an actor element as a blocking gen_server:call — turning this scan into an RPC per element that can raise deadlock_detected or time out. eq/2 tries raw =:= first and only dispatches to tagged value types, so actors answer by identity, as they must.

Examples

#(1, 2, 3) includes: 2      // => true
#(1, 2, 3) includes: 9      // => false
inject: initial into: block

Reduce the collection with an accumulator.

Evaluates block with (accumulator, element) for each element. Returns the final accumulator value.

Kept as @primitive because the pure-BT implementation using do: with local-variable mutation does not work for abstract-class methods: the compiler generates lists:foreach (no state threading) instead of lists:foldl. The Erlang helper calls the block as Block(Acc, Elem) (accumulator first) to match the Beamtalk block value: acc value: each convention expected by collect:, select:, and reject:.

Examples

#(1, 2, 3) inject: 0 into: [:sum :x | sum + x]  // => 6
collect: block

Collect results of evaluating block on each element.

Returns a collection of the same type as the receiver (species pattern). Builds the result in reverse using addFirst: then converts via species withAll:.

Examples

#(1, 2, 3) collect: [:x | x * 2]  // => #(2, 4, 6)
parallelCollect: block

Like collect:, but evaluates block for every element concurrently (one spawned process per element, via Parallel all: — BT-2974) instead of sequentially.

Concurrency is unbounded — one process is spawned per element, with no pooling or throttling. Use parallelCollect:maxConcurrency: for very large collections where that matters.

If any element's block evaluation fails, parallelCollect: re-raises that failure (the first one, in element order) — matching collect:'s own behaviour of propagating an exception raised by block. Use Parallel all: directly (on self collect: [:each | [block value: each]]) if you need every per-element Result, including partial failures, instead of a raise.

Examples

#(1, 2, 3) parallelCollect: [:x | x * 2]  // => #(2, 4, 6)
parallelCollect: block maxConcurrency: maxConcurrency

Like parallelCollect:, but bounds concurrency to maxConcurrency processes at a time instead of spawning one per element.

The receiver is split into consecutive chunks of at most maxConcurrency elements; each chunk runs concurrently (via Parallel all:), and the next chunk only starts once every element of the current one has finished. This is chunked bounded concurrency, not a streaming worker pool — a chunk's slowest element gates the next chunk's start, so a pool where finished slots immediately pick up new work would use fewer total processes over time for uneven workloads. Chunking is simple, correct, and enough to cap resource usage for very large collections; reach for Parallel all: directly with your own work-stealing queue if you need true streaming concurrency.

Raises #type_error if maxConcurrency is not a positive Integer.

Failure behaviour matches parallelCollect:: the first failure (in element order within the failing chunk) is re-raised.

Examples

#(1, 2, 3, 4, 5) parallelCollect: [:x | x * 2] maxConcurrency: 2
  // => #(2, 4, 6, 8, 10)
runChunked: blocks maxConcurrency: maxConcurrency

Runs blocks in consecutive Parallel all: chunks of at most maxConcurrency elements, preserving overall order.

runChunked: blocks maxConcurrency: maxConcurrency acc: acc

Tail-recursive helper for runChunked:maxConcurrency:acc builds up in reverse (each chunk's results prepended via addFirst:, one at a time, so the recursive step stays a genuine BEAM tail call regardless of how many chunks there are) and is reversed once at the end.

select: block

Select elements for which block returns true.

Returns a collection of the same type as the receiver (species pattern). Builds the result in reverse using addFirst: then converts via species withAll:.

Examples

#(1, 2, 3, 4) select: [:x | x > 2]  // => #(3, 4)
reject: block

Reject elements for which block returns true.

Examples

#(1, 2, 3, 4) reject: [:x | x > 2]  // => #(1, 2)
detect: block

Find the first element for which block returns true.

Raises not_found if no element matches — the return type is E, so there is no in-band way to say "nothing matched". Every collection agrees on this: Set, Bag, Dictionary, Interval, and Binary / String inherit this implementation, and the native overrides on List and Stream raise the same kind. detect:ifNone: is the non-raising alternative on all of them.

The error names the receiver's class rather than Collection, so a no-match on a Set reports Set.

Uses ^ (non-local return) for early exit — this compiles to throw/catch on BEAM.

Examples

#(1, 2, 3) detect: [:x | x > 1]     // => 2
detect: block ifNone: noneBlock

Find the first element matching block, or evaluate noneBlock if none.

Uses ^ (non-local return) for early exit — compiles to throw/catch on BEAM.

noneBlock is deliberately Block(Object), not Block(E): the fallback commonly produces a value outside the element type (ifNone: [nil], ifNone: [#missing]), so narrowing it to E would reject those legitimate uses. The trade-off — a wrong-typed default is not flagged — is intentional, and is why the return type is E | Object.

Examples

#(1, 2) detect: [:x | x > 5] ifNone: [0]  // => 0
anySatisfy: block

Test if any element satisfies block.

Uses ^ (non-local return) for early exit — compiles to throw/catch on BEAM.

Examples

#(1, 2, 3) anySatisfy: [:x | x > 2]  // => true
allSatisfy: block

Test if all elements satisfy block.

Uses ^ (non-local return) for early exit — compiles to throw/catch on BEAM.

Examples

#(2, 4, 6) allSatisfy: [:x | x isEven]  // => true
noneSatisfy: block

Test if no element satisfies block.

Examples

#(1, 2, 3) noneSatisfy: [:x | x > 5]  // => true
#(1, 2, 3) noneSatisfy: [:x | x > 2]  // => false
count: block

Count the elements for which block returns true.

Examples

#(1, 2, 3, 4) count: [:x | x > 2]   // => 2
#() count: [:x | x > 2]             // => 0
sum

Sum all elements. Returns 0 for an empty collection.

Uses native numeric addition (intended for Integer/Float); it does not dispatch a Beamtalk + message. Kept as @primitive because the pure-BT fold performs arithmetic on the generic element type E, which the gradual type checker cannot prove is numeric.

Examples

#(1, 2, 3) sum               // => 6
#() sum                      // => 0
max

Return the largest element.

Compares using the runtime's native total ordering (intended for Integer/Float) — it does not dispatch a Beamtalk > message, so a custom > method on the element type is not honoured. Raises a #beamtalk_error on an empty collection — there is no maximum of nothing.

Examples

#(3, 1, 4, 1, 5) max         // => 5
min

Return the smallest element.

Compares using the runtime's native total ordering (intended for Integer/Float) — it does not dispatch a Beamtalk < message. Raises a #beamtalk_error on an empty collection.

Examples

#(3, 1, 4, 1, 5) min         // => 1
average

Return the mean of the elements as a Float.

Uses native numeric addition (intended for Integer/Float). Raises a #beamtalk_error on an empty collection.

Examples

#(1, 2, 3, 4) average        // => 2.5
eachWithIndex: block

Iterate over each element with its 1-based index.

Evaluates block with (element, index) for each element.

Examples

#("a", "b") eachWithIndex: [:item :i | Transcript show: i]
do: block separatedBy: separatorBlock

Iterate over each element, evaluating separatorBlock between elements.

The separator runs between consecutive elements, not before the first or after the last. Useful for joining/formatting.

Examples

#(1, 2, 3) do: [:x | Transcript show: x] separatedBy: [Transcript show: ", "]
asList

Convert to a List, in iteration order.

List is the canonical eager sequence. Note: for a Dictionary this yields its values (consistent with do:); for a Bag, each element is repeated by its occurrence count.

Examples

(1 to: 3) asList                          // => #(1, 2, 3)
(Set withAll: #(1, 2, 3)) asList sort     // => #(1, 2, 3)
asArray

Convert to an Array.

Examples

(1 to: 3) asArray         // => #[1, 2, 3]
asSet

Convert to a Set, discarding duplicates.

Examples

#(1, 2, 2, 3) asSet size  // => 3
asBag

Convert to a Bag, counting occurrences.

Examples

(#(1, 1, 2) asBag) occurrencesOf: 1   // => 2
asString

Return a string representation.

From Value

printString

Return a developer-readable string representation showing fields.

Produces ClassName(field: value, ...) via the canonical structural renderer (ADR 0094). Field values are rendered with their own printString (strings stay quoted, nested values show their structural form), in sorted field order. A class with no fields produces ClassName(). Recursion is bounded by depth/width/length caps with a cycle guard.

Examples

ValuePoint x: 3 y: 4        printString   // => "ValuePoint(x: 3, y: 4)"
ValuePoint new              printString   // => "ValuePoint(x: 0, y: 0)"

From Object

class

Return the class of the receiver.

Examples

42 class              // => Integer
"hello" class         // => String
isNil

Test if the receiver is nil. Returns false for all objects except nil.

Examples

42 isNil              // => false
nil isNil             // => true
notNil

Test if the receiver is not nil. Returns true for all objects except nil.

Examples

42 notNil             // => true
nil notNil            // => false
ifNil: _nilBlock

If the receiver is nil, evaluate nilBlock. Otherwise return self.

_nilBlock is never evaluated on this Object-level definition (only UndefinedObject's override calls it, with Block(R) -> R), so R is unconstrained here — parameterizing it still documents the zero-arg shape without implying this branch produces R (BT-2834).

Examples

42 ifNil: [0]         // => 42
nil ifNil: [0]        // => 0
ifNotNil: notNilBlock

If the receiver is not nil, evaluate notNilBlock with self.

Left as a bare Block deliberately (BT-2834): notNilBlock is invoked one-arg with self and its result becomes the method's own result, so a precise signature needs a Self-in-Block(...) type-arg form (Block(Self, R) -> R) with no precedent elsewhere in stdlib. The type checker doesn't consult this declared signature for ifNotNil: anyway — it narrows the block's parameter from the receiver's own type via infer_args_for_if_not_nil in inference.rs (BT-2046), independent of this stdlib declaration.

Examples

42 ifNotNil: [:v | v + 1]   // => 43
nil ifNotNil: [:v | v + 1]  // => nil
ifNil: _nilBlock ifNotNil: notNilBlock

If nil, evaluate nilBlock; otherwise evaluate notNilBlock with self.

Bare Block params here (unlike UndefinedObject's Block(R) -> R override, BT-2824) are intentional, not an oversight: the type checker never consults this declared signature for these two selectors — it reads the block arguments' actual inferred return types directly (if_nil_branch_union_ret_ty in inference.rs, BT-2047) since a bare -> R here can't express "whatever the block returns" without a Self-in-Block(...) type-arg form with no precedent elsewhere in stdlib.

Examples

42 ifNil: [0] ifNotNil: [:v | v + 1]    // => 43
nil ifNil: [0] ifNotNil: [:v | v + 1]   // => 0
ifNotNil: notNilBlock ifNil: _nilBlock

If not nil, evaluate notNilBlock with self; otherwise evaluate nilBlock.

See ifNil:ifNotNil: above — the bare Block params are intentional.

Examples

42 ifNotNil: [:v | v + 1] ifNil: [0]    // => 43
nil ifNotNil: [:v | v + 1] ifNil: [0]   // => 0
printString

Return the developer-readable (Debug) string representation.

printString is the Debug protocol (ADR 0094): the self-describing, structural form used by the REPL, logs, and by any other printString that nests this object. It is the REPL default — evaluating an expression shows its printString.

This default returns the bare class name (no a/an article — the old "a ClassName" form was dropped in ADR 0094). Value overrides it with the structural ClassName(field: value, ...) form, actors render as Actor(ClassName, pid), supervisors as Supervisor(ClassName, pid) / DynamicSupervisor(ClassName, pid), and primitive types (Integer, String, List, …) override it with their own richer output. Authors rarely override printString directly — the default is derived.

Examples

42 printString            // => "42"
displayString

Return the user-facing (Display) string representation.

displayString is the Display protocol (ADR 0094): the human-facing form. It is the hook the language pulls during string interpolation — every {...} segment renders via the value's displayString. Developers rarely call it directly; they override it when a value has a natural human rendering (e.g. Money$10.50, where printString would still show the Debug form).

It defaults to printString, so most types need no override. String and Symbol demonstrate the split: "hi" printString"\"hi\"" (quoted, Debug) while "hi" displayString"hi" (plain, Display); likewise #foo drops its # prefix under displayString.

displayString is not part of the Printable protocol (deferred per ADR 0094 §5).

Examples

42 displayString             // => "42"
inspect

Open a navigable Inspector cursor on the receiver.

ADR 0095 Phase 3 (BT-2504). inspect is repurposed from -> String (the ADR-0094 deferral) to the verb that produces an Inspector — a live, immutable cursor for drilling into the object (Inspector on: self). anObject inspect is the shorthand; Inspector on: anObject is the explicit spelling. The cursor exposes fields/at:/path/refresh/ printString (an indented text tree) and asDictionaries (the MCP/browser wire form); see Inspector.

This is a breaking change: code that used inspect for its old String result must switch to printString (the structural Debug string, ADR 0094) — a transitional lint flags inspect used directly in ++/ string position.

Examples

42 inspect kind                  // => #value
(Point x: 3 y: 4) inspect fields size   // => 2
(Point x: 3 y: 4) printString    // => "Point(x: 3, y: 4)"  (the old inspect string)
yourself Sealed

Return the receiver itself. Useful for cascading side effects.

Examples

42 yourself            // => 42
hash

Return a hash value for the receiver.

Examples

42 hash
equals: other

Test value equality — the overridable counterpart to =:=.

Defaults to =:= (Erlang structural term equality), so for most classes the two agree. Unlike =:=, this is an ordinary message send, so a class whose logical value is not its representation can override it: a persistent structure whose shape depends on construction history, a timestamp that should compare by instant rather than by wall-clock fields, or a type with a normalising form. =:=, =/=, == and /= are lowered straight to Erlang BIFs (ADR 0002) and cannot be overridden — the compiler rejects any attempt (BT-2997).

What honours it

The linear scans: includes: on Collection, List, Array and Dictionary (which searches values), plus List>>indexOf: and TestCase>>assert:equals:.

Contract

An override must agree with =:= wherever =:= holds — a =:= b must imply a equals: b. It may only make more values equal, never fewer. The scans above rely on this: each tries raw =:= first and dispatches only on a miss, so a fast-path hit is always a genuine equals: hit.

Caveat

Set, Dictionary keys, and List>>unique decide identity in the VM with raw =:=, never through this method — keying and deduplication need an order or a hash that a user-defined equals: cannot supply. A class that overrides equals: still deduplicates by representation when used as a key or element. Normalise the representation if that matters.

Examples

42 equals: 42           // => true
42 equals: 42.0         // => false (defaults to strict `=:=`)
"ab" equals: "ab"       // => true
respondsTo: selector Sealed

Test if the receiver responds to the given selector.

Examples

42 respondsTo: #abs    // => true
fieldNames Sealed

Return the names of fields.

Examples

42 fieldNames             // => #()
fieldAt: name Sealed

Return the value of the named field.

Examples

object fieldAt: #name
fieldAt: name put: value Sealed

Set the value of the named field (returns new state).

Examples

object fieldAt: #name put: "Alice"
perform: selector Sealed

Send a unary message dynamically.

Examples

42 perform: #abs       // => 42
perform: selector withArguments: args Sealed

Send a message dynamically with arguments.

Examples

3 perform: #max: withArguments: #(5)   // => 5
subclassResponsibility

Raise an error indicating this method must be overridden by a subclass.

Examples

self subclassResponsibility
notImplemented

Raise an error indicating this method has not yet been implemented.

Use this for work-in-progress stubs. Distinct from subclassResponsibility, which signals an interface contract violation.

Examples

self notImplemented
show: aValue

Send aValue to the current transcript without a trailing newline.

Nil-safe: does nothing when no transcript is set (batch compile, tests).

Examples

42 show: "value: "
showCr: aValue

Send aValue to the current transcript followed by a newline.

Nil-safe: does nothing when no transcript is set (batch compile, tests).

Examples

42 showCr: "hello world"
isKindOf: aClass

Test if the receiver is an instance of aClass or any of its subclasses.

For class-object receivers, follows Smalltalk semantics: self class is the metaclass, so the check walks the parallel metaclass hierarchy. The parallel chain is grounded at ProtoObject class superclass == Class (ADR 0036), so the metaclass tower merges into the instance-side Class → Behaviour → Object → ProtoObject chain. As a result, Integer isKindOf: Object and Integer isKindOf: Class both return true.

Examples

42 isKindOf: Integer        // => true
42 isKindOf: Object         // => true
#foo isKindOf: Symbol       // => true
#foo isKindOf: String       // => false
Integer isKindOf: Number    // => false (metaclass chain, not instance chain)
Integer isKindOf: Number class  // => true  (Number class is in the parallel chain)
Integer isKindOf: Object    // => true (grounded — Object is reachable via the metaclass tower)
Integer isKindOf: Class     // => true (Integer class inherits from Class)
error: message

Raise an error with the given message.

Examples

self error: "something went wrong"
delegate Sealed

Delegate message dispatch to the backing Erlang module (ADR 0101, BT-2720).

This method is a sentinel — a plain Object has no backing Erlang module, so calling delegate raises an Error at runtime. Stateless Objects declared with native: have their self delegate method bodies rewritten by the compiler's codegen phase to call the backing module directly, so the sentinel is never reached on a native: class.

Unlike Actor's delegate (visible only to Actor subclasses), this Object-base sentinel is visible to every class, so delegate is a reserved selector on the Object protocol.

Examples

42 delegate   // => ERROR: delegate called on a non-native Object

From ProtoObject

== other

Test value equality (Erlang ==, non-strict — 1 == 1.0 is true).

Examples

42 == 42           // => true
"abc" == "abc"     // => true
/= other

Test value inequality (negation of ==).

Examples

1 /= 2             // => true
42 /= 42           // => false
=:= other

Test strict value equality (Erlang =:=1 =:= 1.0 is false, unlike ==).

Every object supports this at runtime (it lowers directly to Erlang's =:= operator regardless of receiver type, ADR 0002) — declared here, once, so it is visible in method listings/completions/respondsTo: for every class, not just the handful (Integer, String, ...) that separately redeclare it with a narrower, class-typed other for documentation purposes.

Examples

1 =:= 1             // => true
1 =:= 1.0           // => false (strict — different types)
(Dictionary new) =:= #{}   // => true
=/= other

Test strict value inequality (negation of =:=).

Examples

1 =/= 1.0           // => true (strict — different types)
1 =/= 1             // => false
class

Return the class of the receiver.

Examples

42 class            // => Integer
"hello" class       // => String
doesNotUnderstand: selector args: arguments

Handle messages the receiver does not understand. Override for custom dispatch.

Examples

42 unknownMessage   // => ERROR: does_not_understand
perform: selector withArguments: arguments

Send a message dynamically with an arguments list.

Examples

42 perform: #abs withArguments: #()   // => 42
performLocally: selector withArguments: arguments

Execute a class method in the caller's process, bypassing gen_server dispatch.

The caller takes responsibility for knowing the method does not mutate class state. Useful for long-running class methods that would otherwise block the class object's gen_server.

Limitations: only resolves methods defined directly on the target class module (does not walk the superclass chain). Class variables and self are not available to the method (nil and #{} are passed).

Examples

MyClass performLocally: #run:ctx: withArguments: #(input, ctx)
perform: selector withArguments: arguments timeout: timeoutMs

Send a message dynamically with an arguments list and explicit timeout.

The timeout (in milliseconds or #infinity) applies to the gen_server:call when the receiver is an actor. For value types, timeout is ignored.

Examples

actor perform: #query withArguments: #(sql) timeout: 30000