Ets

Inherits from Object

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

SymbolDescription
#setOne entry per key (default, unordered)
#orderedSetOne entry per key, keys sorted
#bagMultiple entries per key, values must differ
#duplicateBagMultiple 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

Class Methods

new: name type: tableType Sealed source

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
named: name Sealed source

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
exists: name Sealed source

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
newOrExisting: name type: tableType Sealed source

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

at: key source

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
at: key put: value source

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
at: key ifAbsent: block source

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
includesKey: key source

Return true if the table contains an entry for key.

Examples

cache includesKey: "key"    // => true or false
removeKey: key source

Remove the entry for key. Returns nil. Idempotent if key is absent.

Examples

cache removeKey: "oldKey"
keys source

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")
size source

Return the number of entries in the table.

Examples

cache size    // => 3
delete source

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

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.

Examples

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

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

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.

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.

Examples

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

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"
displayString

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

Inspect the receiver.

Examples

42 inspect             // => "42"
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
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.

Examples

42 isKindOf: Integer    // => true
42 isKindOf: Object     // => true
#foo isKindOf: Symbol   // => true
#foo isKindOf: String   // => false
error: message

Raise an error with the given message.

Examples

self error: "something went wrong"

From ProtoObject

== other

Test value equality (Erlang ==).

Examples

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

Test value inequality (negation of ==).

Examples

1 /= 2             // => true
42 /= 42           // => 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