File

Inherits from Object

File — File system operations.

Provides file I/O operations and lazy file streaming using Erlang's file module. All operations are class methods. Errors use structured #beamtalk_error{} records.

Examples

File exists: "test.txt"
File readAll: "test.txt"
File writeAll: "output.txt" contents: "hello"
File readBinary: "image.png"
File writeBinary: "output.bin" contents: data
File appendBinary: "log.bin" contents: data
(File lines: "data.csv") do: [:line | Transcript show: line]
File open: "data.csv" do: [:handle | handle lines take: 10]
File open: "events.log" mode: #append do: [:h | h writeLine: "e". h sync]

@see System (for environment variables and OS information) @see Json (for reading/writing JSON files)

Class Methods

exists: path Sealed source

Test if a file exists at the given path (class method).

Examples

File exists: "test.txt"   // => true or false
readAll: path Sealed source

Read the entire contents of a file as a string (class method).

Returns Result ok: contents on success, or Result error: err on failure.

Examples

File readAll: "test.txt"  // => Result ok: "file contents..."
writeAll: path contents: text Sealed source

Write text to a file, creating or overwriting it (class method).

Returns Result ok: nil on success, or Result error: err on failure.

Examples

File writeAll: "output.txt" contents: "hello"
readBinary: path Sealed source

Read the entire contents of a file as raw binary (class method).

Returns Result ok: binary on success, or Result error: err on failure. Unlike readAll:, this does not assume the contents are a UTF-8 string.

Examples

File readBinary: "image.png"  // => Result ok: <<...>>
writeBinary: path contents: binary Sealed source

Write binary data to a file, creating or overwriting it (class method).

Returns Result ok: nil on success, or Result error: err on failure.

Examples

File writeBinary: "output.bin" contents: data
appendBinary: path contents: binary Sealed source

Append binary data to a file, creating it if needed (class method).

Returns Result ok: nil on success, or Result error: err on failure.

Examples

File appendBinary: "log.bin" contents: data
lines: path Sealed source

Return a lazy Stream of lines from a file (class method).

Opens the file and returns Result ok: stream on success, or Result error: err on failure. The Stream reads one line at a time and closes the handle automatically when exhausted. Constant memory — safe for large files.

Cross-process constraint: file-backed Streams must be consumed by the same process that created them.

Examples

(File lines: "data.csv") unwrap take: 5
(File lines: "log.txt") unwrap select: [:l | l includesSubstring: "ERROR"]
open: path do: block Sealed source

Block-scoped file handle with automatic cleanup (class method).

Opens the file, passes a FileHandle to the block, and ensures the handle is closed when the block exits (normally or via exception). Returns Result ok: blockResult on success, or Result error: err on failure.

The handle responds to lines which returns a Stream of lines. Both the handle and any Streams derived from it must be consumed within the block — they must not escape, as the file descriptor is closed when the block returns.

The block runs in your own process (ADR 0109), so it may call File again.

Examples

(File open: "data.csv" do: [:handle |
  handle lines take: 10
]) unwrap
open: path mode: mode Sealed source

Open a file in the given mode and return a FileHandle (class method).

Modes:

ModeBehaviour
#readRead only; the file must exist
#writeTruncate or create, write only
#appendCreate if absent; every write goes to the end
#readWriteCreate if absent; existing contents kept

Write-capable modes create missing parent directories. Returns Result ok: handle, or Result error: err.

The caller owns the handle and must close it, but is not the only backstop: it is registered against the REPL session if there is one, else the calling actor, else left unowned, and closed automatically when that owner dies. File openHandles lists every outstanding handle for diagnostics. Prefer open:mode:do: whenever a block scope will do — it needs no owner at all.

Examples

handle := (File open: "events.log" mode: #append) unwrap
handle writeLine: "started".
handle sync.
handle close.
open: path mode: mode do: block Sealed source

Block-scoped handle in the given mode, closed however the block exits (class method).

Opens the file, passes the FileHandle to the block, and guarantees the handle is closed on the way out — normal return, raised error, or non-local return alike. Returns Result ok: blockResult on success, or Result error: err if the file could not be opened.

The handle must not escape the block; the descriptor is closed when the block returns. See open:mode: for the mode Symbols.

The block runs in your own process (ADR 0109), so it may call File again, holds nothing else up, and is under no time limit.

Examples

(File open: "events.log" mode: #append do: [:handle |
  handle writeLine: "an event".
  handle sync
]) unwrap
lastModified: path Sealed source

Get the last modification time of a file (class method).

Returns Result ok: DateTime on success, or Result error: err if the file does not exist.

Examples

File lastModified: "test.txt"  // => Result ok: a DateTime(...)
isDirectory: path Sealed source

Test if a path refers to a directory (class method).

Examples

File isDirectory: "target"   // => true or false
isFile: path Sealed source

Test if a path refers to a regular file (class method).

Examples

File isFile: "test.txt"   // => true or false
mkdir: path Sealed source

Create a directory (class method). Error if the parent does not exist.

Returns Result ok: nil on success, or Result error: err on failure.

Examples

File mkdir: "target/mydir"
mkdirAll: path Sealed source

Create a directory and all missing parent directories (class method).

Returns Result ok: nil on success, or Result error: err on failure.

Examples

File mkdirAll: "target/a/b/c"
listDirectory: path Sealed source

List entries in a directory as a List of Strings (class method).

Returns Result ok: list on success, or Result error: err on failure.

Examples

File listDirectory: "target"
delete: path Sealed source

Delete a file or empty directory (class method).

Returns Result ok: nil on success, or Result error: err on failure.

Examples

File delete: "target/old.txt"
deleteAll: path Sealed source

Recursively delete a directory tree (class method).

Returns Result ok: nil on success, or Result error: err on failure.

Examples

File deleteAll: "target/old-workspace"
rename: from to: to Sealed source

Rename or move a file or directory (class method).

Returns Result ok: nil on success, or Result error: err on failure.

Examples

File rename: "old.txt" to: "new.txt"
absolutePath: path Sealed source

Resolve a relative path to its absolute path (class method).

Returns Result ok: absPath on success, or Result error: err on failure.

Examples

File absolutePath: "target/test.txt"
cwd Sealed source

Return the current working directory (class method).

Examples

File cwd   // => "/home/user/projects/myapp"
tempDirectory Sealed source

Return the OS temporary directory path (class method).

Examples

File tempDirectory
openHandles Sealed source

List every outstanding open:mode: handle for diagnostics (class method).

Returns an Array of 3-element Arrays #(path mode owner). owner is the REPL session or actor pid that opened the handle, or nil if it was opened from compiled code with neither. Handles from open:do: and open:mode:do: never appear — they are block-scoped and always closed before the call returns.

Examples

h := (File open: "events.log" mode: #append) unwrap.
File openHandles   // => #(#("events.log" #append <a Pid> or nil))
h close.

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.

_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