Result

Inherits from Value
Sealed

Result — Value type for expected success/failure outcomes (ADR 0060).

Result is a sealed value class representing either a successful outcome (ok:) or a failure (error:). Use Result for operations where failure is a normal, expected case — file I/O, parsing, network requests. Use exceptions (on:do:) for programming errors like wrong argument types.

Constructors

Result ok: 42               // => a successful Result holding 42
Result error: #file_not_found   // => a failed Result
Result tryDo: [expr]         // => wraps exception-raising code

Combinators

(Result ok: 42) map: [:v | v + 1]              // => Result ok: 43
(Result ok: 42) andThen: [:v | Result ok: v * 2]  // => Result ok: 84
(Result error: #nope) map: [:v | v + 1]        // => Result error: #nope
(Result ok: 42) valueOr: 0                     // => 42
(Result error: #nope) valueOr: 0               // => 0
(Result ok: 42) ifOk: [:v | v] ifError: [:e | 0]  // => 42

When to Use Result vs Exceptions

Failure modeUse
File not found, parse errorResult
does_not_understand, arity errorException
User input validationResult
Actor lifecycle errorsException

@see Exception (for exception-based error handling) @see Error (for exception subclass with reason codes)

Class Methods

ok: value source

Create a successful Result wrapping a value (class method).

Examples

Result ok: 42          // => Result ok: 42
Result ok: "hello"     // => Result ok: "hello"
Result ok: nil         // => Result ok: nil
error: reason source

Create a failed Result wrapping an error reason (class method).

The reason should be a structured error (Exception subclass instance or #beamtalk_error{}). Bare symbols are accepted for convenience but FFI wrappers must provide structured errors at public boundaries.

Examples

Result error: #not_found   // => Result error: #not_found
Result error: Error new    // => Result error: <Error>

To capture a raised exception as a Result, use Result tryDo: [Error signal: "oops"].

tryDo: block Sealed source

Evaluate a block and return a Result (class method).

If the block succeeds, returns Result ok: value. If the block raises an exception, returns Result error: theException. Bridges between exception-raising legacy code and Result combinators.

Examples

Result tryDo: [42]                          // => Result ok: 42
Result tryDo: [Exception signal: "oops"]   // => Result error: <Exception>
Result tryDo: [(File readAll: "missing.txt") unwrap] // => Result error: <Exception>
fromTuple: tuple source

Convert an Erlang-style tagged tuple to a Result (class method).

Accepts {ok, V} and {error, R} tuples from Erlang messages or other non-FFI sources. Raises on tuples that are not ok/error tagged.

Examples

Result fromTuple: (Tuple withAll: #(#ok, 42))       // => Result ok: 42
Result fromTuple: (Tuple withAll: #(#error, #oops)) // => Result error: ...

Instance Methods

ok Sealed source

True if this Result holds a success value.

Examples

(Result ok: 42) ok      // => true
(Result error: #x) ok   // => false
isError Sealed source

True if this Result holds an error.

Examples

(Result ok: 42) isError      // => false
(Result error: #x) isError   // => true
value Sealed source

The success value. Raises if this is an error Result.

Prefer valueOr:, valueOrDo:, or ifOk:ifError: for safe access.

Examples

(Result ok: 42) value     // => 42
(Result error: #x) value  // => Exception: Cannot access 'value'...
error Sealed source

The error reason. Raises if this is an ok Result.

Prefer ifOk:ifError: or mapError: for safe access.

Examples

(Result error: #x) error  // => #x
(Result ok: 42) error     // => Exception: Cannot access 'error'...
valueOr: default Sealed source

Unwrap the success value, or return the default if error.

Examples

(Result ok: 42) valueOr: 0    // => 42
(Result error: #x) valueOr: 0 // => 0
valueOrDo: block Sealed source

Unwrap the success value, or evaluate a block with the error reason.

Examples

(Result ok: 42) valueOrDo: [:e | 0]       // => 42
(Result error: #x) valueOrDo: [:e | -1]   // => -1
unwrap Sealed source

Unwrap the success value, or raise an exception.

Re-raises the errReason directly if it is an Exception (preserving class, message, and hints). For raw values, signals a generic Error.

Examples

(Result ok: 42) unwrap         // => 42
(Result error: #x) unwrap      // => Exception: unwrap called on Result error: #x
map: block Sealed source

Apply a block to the success value, wrapping result in a new ok Result. If this is an error, returns self unchanged.

Examples

(Result ok: 42) map: [:v | v + 1]        // => Result ok: 43
(Result error: #x) map: [:v | v + 1]     // => Result error: #x
andThen: block Sealed source

Apply a block that returns a Result. Flattens the nesting. If this is an error, returns self unchanged.

Examples

(Result ok: 42) andThen: [:v | Result ok: v * 2]   // => Result ok: 84
(Result error: #x) andThen: [:v | Result ok: v]    // => Result error: #x
mapError: block Sealed source

Apply a block to the error reason, wrapping result in a new error Result. If this is ok, returns self unchanged.

Examples

(Result error: #x) mapError: [:e | "wrapped: " ++ e printString]
  // => Result error: "wrapped: #x"
(Result ok: 42) mapError: [:e | "oops"]   // => Result ok: 42
ifError: block Sealed source

Evaluate a block with the error reason if this is an error; return self if ok.

Use at the end of an andThen:/map: chain as a shared terminal error handler. The error case is handled by the block; the ok case is passed through unchanged.

Examples

(Result ok: 42) ifError: [:e | 0]             // => Result ok: 42
(Result error: #oops) ifError: [:e | e]        // => #oops
chain := (Result ok: 1) andThen: [:v | Result error: #fail].
chain ifError: [:_ | "handled"]                // => "handled"
ifOk: okBlock ifError: errorBlock Sealed source

Handle both ok and error cases with blocks.

Examples

(Result ok: 42) ifOk: [:v | v + 1] ifError: [:e | -1]    // => 43
(Result error: #x) ifOk: [:v | v] ifError: [:e | 0]      // => 0
printString Sealed source

Human-readable representation: "Result ok: value" or "Result error: reason".

Examples

(Result ok: 42) printString       // => "Result ok: 42"
(Result error: #x) printString    // => "Result error: #x"

Inherited Methods

From Value

inspect

Return a developer-readable string representation showing fields.

Produces ClassName(field: value, ...). Field values are recursively inspected — strings are quoted, nested objects show their own inspect. A class with no fields produces ClassName().

Examples

ValuePoint x: 3 y: 4        inspect   // => "ValuePoint(x: 3, y: 4)"
ValuePoint new              inspect   // => "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.

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