ChangeLog
ChangeLog — Navigable view of the workspace's pending in-memory changes (ADR 0082 Phase 1).
Returned by Workspace changes, following Pharo's Smalltalk changes
idiom. The ChangeLog is the append-only record of every live method
mutation and the workspace's dirty-state tracker — "what has the running
workspace changed relative to disk?".
A ChangeLog snapshot holds every logged entry, but its default collection
views (size, isEmpty, notEmpty, do:, dirtyMethods) reflect only
the active entries: changes from the current epoch that have not been
orphaned. Prior-epoch and orphan entries (whose memory state was lost on
workspace restart, so they are no longer re-appliable) are excluded from
those views — but select: ranges over the full set, so it can still reach
them (e.g. Workspace changes select: [:e | e isOrphan]).
Backed by beamtalk_workspace_changelog.erl via FFI.
Examples
Workspace changes notEmpty // => false
Workspace changes dirtyMethods // => #{}
Workspace changes do: [:e | Transcript show: e printString]
Workspace changes select: [:e | e isOrphan] // => _
Methods
Instance Methods
Return the active entries: current epoch, not orphaned, not shadowed by a newer entry for the same method, and not clean (still differing from disk).
This is the live, dirty-relative-to-disk set that the default collection
views operate on. Repeated patches/reverts of one method (a revert is
itself a patch, ADR 0082 "Undo") collapse to the latest entry — the one
Workspace flush would apply. A method reverted back to exactly its
on-disk body has no net change, so it drops out entirely ("disappear when
clean", BT-2575). select: (which reaches orphaned, shadowed, and clean
entries) uses the full set instead, so the audit trail stays complete.
Return all entries, including prior-epoch and orphan entries.
Examples
Workspace changes allEntries // => _
The number of active (live, re-appliable) changes.
Examples
Workspace changes size // => 0
Whether there are no active changes.
Examples
Workspace changes isEmpty // => true
Whether there is at least one active change.
"Is anything dirty?" is Workspace changes notEmpty.
Examples
Workspace changes notEmpty // => false
Iterate over each active entry, evaluating block with it.
Prior-epoch and orphan entries are skipped — use select: to reach them.
Examples
Workspace changes do: [:e | Transcript show: e authorKind]
Select entries for which block returns true, over the full entry set.
Unlike the other collection views, select: ranges over every entry —
including prior-epoch and orphan entries — so it can still reach them.
Examples
Workspace changes select: [:e | e isOrphan] // orphans only
Workspace changes select: [:e | e isAgent] // agent changes only
Return the dirty methods grouped by class: #{Class -> #{selectors}}.
Derived from the active entries only. Each class maps to a Set of patched
selector Symbols; new-class entries appear under their class with the
placeholder selector #'new-class'.
Examples
Workspace changes dirtyMethods // => #{} (nothing patched)
// After `Counter >> increment => ...`:
// Workspace changes dirtyMethods // => #{#Counter => #{#increment}}
Re-install the prior body of anEntry's method, undoing the patch
(ADR 0082 Phase 4).
The re-install is itself a durable patch that emits a fresh ChangeEntry —
the original entry is preserved in the log so the audit history is intact.
anEntry is a ChangeEntry obtained from do: / select:. Raises a
structured error when the entry's method has no active prior body to
restore, when the entry is a #'new-class' creation (destructive — out of
scope for this phase), or when re-installing the prior body fails to
compile.
Returns the patched class object (matching compile:source:).
Examples
Workspace changes do: [:e | e isAgent ifTrue: [Workspace changes revert: e]]
Discard every pending ChangeLog entry without writing to disk (ADR 0082 Phase 4).
The on-disk metadata segment is truncated so the audit log is reset. Memory still holds the latest patched method versions until the next workspace restart, when disk wins (matching the ADR contract). Idempotent: clearing an empty log is a successful no-op. Returns the receiver so calls chain like the other ChangeLog operations.
Examples
Workspace changes clear // => _
Internal FFI seam (ADR 0101 Part 4): discard every pending entry. Keeps
clear pure Beamtalk.
Flush only the ChangeEntries whose kind or author_kind is in kinds
(ADR 0082 Phase 4).
kinds is a Set (or List) of Symbols. Allowed values:
- entry kinds:
#instance,#class,#'new-class' - author kinds:
#human,#agent
When both an entry-kind and an author-kind symbol are present, the entry
must satisfy both dimensions (e.g. #{#agent, #'new-class'} flushes only
agent-authored new-class entries). Unknown symbols and an empty set are
rejected with a structured error.
Returns the same FlushResult summary as Workspace flush.
Examples
Workspace changes flushKinds: #{#agent} // => _
Workspace changes flushKinds: #{#'new-class'} // => _
Workspace changes flushKinds: #{#agent, #instance} // => _
Developer-readable representation, e.g. "ChangeLog with 2 entries".
Examples
Workspace changes printString // => "ChangeLog with 0 entries"
Inherited Methods
From Value
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
Return the class of the receiver.
Examples
42 class // => Integer
"hello" class // => String
Test if the receiver is nil. Returns false for all objects except nil.
Examples
42 isNil // => false
nil isNil // => true
Test if the receiver is not nil. Returns true for all objects except nil.
Examples
42 notNil // => true
nil notNil // => false
If the receiver is nil, evaluate nilBlock. Otherwise return self.
Examples
42 ifNil: [0] // => 42
nil ifNil: [0] // => 0
If the receiver is not nil, evaluate notNilBlock with self.
Examples
42 ifNotNil: [:v | v + 1] // => 43
nil ifNotNil: [:v | v + 1] // => nil
If nil, evaluate nilBlock; otherwise evaluate notNilBlock with self.
Examples
42 ifNil: [0] ifNotNil: [:v | v + 1] // => 43
nil ifNil: [0] ifNotNil: [:v | v + 1] // => 0
If not nil, evaluate notNilBlock with self; otherwise evaluate nilBlock.
Examples
42 ifNotNil: [:v | v + 1] ifNil: [0] // => 43
nil ifNotNil: [:v | v + 1] ifNil: [0] // => 0
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"
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"
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)
Return the receiver itself. Useful for cascading side effects.
Examples
42 yourself // => 42
Return a hash value for the receiver.
Examples
42 hash
Test if the receiver responds to the given selector.
Examples
42 respondsTo: #abs // => true
Return the names of fields.
Examples
42 fieldNames // => #()
Return the value of the named field.
Examples
object fieldAt: #name
Set the value of the named field (returns new state).
Examples
object fieldAt: #name put: "Alice"
Send a unary message dynamically.
Examples
42 perform: #abs // => 42
Send a message dynamically with arguments.
Examples
3 perform: #max: withArguments: #(5) // => 5
Raise an error indicating this method must be overridden by a subclass.
Examples
self subclassResponsibility
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
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: "
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"
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)
Raise an error with the given message.
Examples
self error: "something went wrong"
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
Test value equality (Erlang ==).
Examples
42 == 42 // => true
"abc" == "abc" // => true
Test value inequality (negation of ==).
Examples
1 /= 2 // => true
42 /= 42 // => false
Return the class of the receiver.
Examples
42 class // => Integer
"hello" class // => String
Handle messages the receiver does not understand. Override for custom dispatch.
Examples
42 unknownMessage // => ERROR: does_not_understand
Send a message dynamically with an arguments list.
Examples
42 perform: #abs withArguments: #() // => 42
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)
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