Ets
Ets — shared in-memory table for actor state sharing.
Wraps OTP ets tables with a Beamtalk-friendly API. Tables are named and public by default, enabling cross-actor reads and writes without message-passing overhead.
ETS tables are owned by the creating process. When the owner terminates, the table is deleted automatically unless an heir is configured.
Table Types
| Symbol | Description |
|---|---|
#set | One entry per key (default, unordered) |
#orderedSet | One entry per key, keys sorted |
#bag | Multiple entries per key, values must differ |
#duplicateBag | Multiple identical entries per key allowed |
Examples
cache := Ets new: #myCache type: #set
cache at: "key" put: 42
cache at: "key" // => 42
cache at: "missing" // => nil
cache at: "missing" ifAbsent: [0] // => 0
cache includesKey: "key" // => true
cache size // => 1
cache removeKey: "key"
cache delete
Cross-Actor Sharing
cache := Ets new: #sharedCache type: #set
// In another actor — retrieve by name:
shared := Ets named: #sharedCache
shared at: "counter" put: 1
Methods
Class Methods
Create a new named public ETS table (class method).
tableType must be one of: #set, #orderedSet, #bag, #duplicateBag.
The table is created as named_table with public access so that any
process can read and write it. Raises already_exists if a table with
the same name already exists.
Examples
cache := Ets new: #myCache type: #set
counters := Ets new: #counters type: #set
Look up an existing named ETS table (class method).
Returns an Ets instance if a table with the given name exists.
Raises not_found if no table with that name has been created.
Examples
cache := Ets named: #myCache
Check whether a named ETS table exists.
Returns true if a table with the given name exists, false otherwise.
Examples
Ets exists: #myCache // => false
Ets new: #myCache type: #set
Ets exists: #myCache // => true
Create a named table or return the existing one.
If a table with the given name already exists, returns an Ets instance
wrapping it. Otherwise creates a new table with the specified type.
This is useful in setUp/tearDown cycles where the previous owner may
still be alive.
Examples
table := Ets newOrExisting: #events type: #set
Instance Methods
Look up a key. Returns the value, or nil if the key is absent.
For #bag and #duplicateBag tables with multiple entries per key,
returns the first stored value. The current wrapper exposes only one
value per key; bag tables are best suited for single-value-per-key use.
Examples
cache at: "key" // => value or nil
Insert or replace a key-value pair. Returns nil.
For #bag and #duplicateBag tables, all existing entries for key
are removed before the new entry is inserted, giving best-effort
upsert semantics. Concurrent writes from multiple actors to the same
key on a bag table are not serialized — interleaved operations may
result in multiple entries for that key.
Examples
cache at: "counter" put: 1
Look up a key; if absent, evaluate the block and return its result.
For #bag and #duplicateBag tables with multiple entries per key,
returns the first stored value (same as at:); the block is not called.
Examples
cache at: "missing" ifAbsent: [0] // => 0
cache at: "key" ifAbsent: [0] // => stored value
Return true if the table contains an entry for key.
Examples
cache includesKey: "key" // => true or false
Remove the entry for key. Returns nil. Idempotent if key is absent.
Examples
cache removeKey: "oldKey"
Return all keys in the table as a List.
Order is unspecified for #set and #bag tables.
Keys are sorted for #orderedSet tables.
For #bag and #duplicateBag tables, each key appears only once.
Examples
cache keys // => #("key1", "key2")
Return the number of entries in the table.
Examples
cache size // => 3
Destroy the table, freeing all memory. Returns nil.
Only the process that created the table (the owner) may call delete.
After calling delete, this Ets instance is no longer valid.
Any further operations on the deleted table will raise an error.
Examples
cache delete
Inherited Methods
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 a developer-readable string representation.
Default implementation returns "a ClassName". Subclasses such as
Integer, String, and List override this to return richer output.
Examples
42 printString // => "42"
Return a user-facing string representation for display purposes.
Default implementation delegates to printString. Subclasses such as
String and Symbol override this to return a more readable form without
developer annotations (e.g. no surrounding quotes or # prefix).
Examples
42 displayString // => "42"
Inspect the receiver.
Examples
42 inspect // => "42"
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.
Examples
42 isKindOf: Integer // => true
42 isKindOf: Object // => true
#foo isKindOf: Symbol // => true
#foo isKindOf: String // => false
Raise an error with the given message.
Examples
self error: "something went wrong"
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