# Actors and Modules Cell organizes code into two types of scripts: **modules** (`.cm`) and **actors** (`.ce`). ## The Actor Model Cell is built on the actor model of computation. Each actor: - Has its own **isolated memory** — actors never share state - Runs to completion each **turn** — no preemption - Performs its own **garbage collection** - Communicates only through **message passing** This isolation makes concurrent programming safer and more predictable. ## Modules (.cm) A module is a script that **returns a value**. The returned value is cached and frozen (made stone). ```javascript // math_utils.cm var math = use('math/radians') function distance(x1, y1, x2, y2) { var dx = x2 - x1 var dy = y2 - y1 return math.sqrt(dx * dx + dy * dy) } function midpoint(x1, y1, x2, y2) { return { x: (x1 + x2) / 2, y: (y1 + y2) / 2 } } return { distance: distance, midpoint: midpoint } ``` **Key properties:** - **Must return a value** — it's an error not to - **Executed once per actor** — subsequent `use()` calls return the cached value - **Return value is stone** — immutable, safe to share - Modules can import other modules with `use()` ### Using Modules ```javascript var utils = use('math_utils') var d = utils.distance(0, 0, 3, 4) // 5 ``` ## Actors (.ce) An actor is a script that **does not return a value**. It runs as an independent unit of execution. ```javascript // worker.ce log.console("Worker started") $on_message = function(msg) { log.console("Received:", msg) // Process message... } ``` **Key properties:** - **Must not return a value** — it's an error to return - Has access to **actor intrinsics** (functions starting with `$`) - Runs until explicitly stopped or crashes ## Actor Intrinsics Actors have access to special functions prefixed with `$`: ### $me Reference to the current actor. ```javascript log.console($me) // actor reference ``` ### $stop() Stop the current actor. ```javascript $stop() ``` ### $send(actor, message, callback) Send a message to another actor. ```javascript $send(other_actor, {type: "ping", data: 42}, function(reply) { log.console("Got reply:", reply) }) ``` Messages are automatically **splatted** — flattened to plain data without prototypes. ### $start(callback, program) Start a new actor from a script. ```javascript $start(function(new_actor) { log.console("Started:", new_actor) }, "worker") ``` ### $delay(callback, seconds) Schedule a callback after a delay. ```javascript $delay(function() { log.console("5 seconds later") }, 5) ``` ### $clock(callback) Get called every frame/tick. ```javascript $clock(function(dt) { // Called each tick with delta time }) ``` ### $receiver(callback) Set up a message receiver. ```javascript $receiver(function(message, reply) { // Handle incoming message reply({status: "ok"}) }) ``` ### $portal(callback, port) Open a network port. ```javascript $portal(function(connection) { // Handle new connection }, 8080) ``` ### $contact(callback, record) Connect to a remote address. ```javascript $contact(function(connection) { // Connected }, {host: "example.com", port: 80}) ``` ### $time_limit(requestor, seconds) Wrap a requestor with a timeout. ```javascript $time_limit(my_requestor, 10) // 10 second timeout ``` ## Module Resolution When you call `use('name')`, Cell searches: 1. **Current package** — files relative to package root 2. **Dependencies** — packages declared in `cell.toml` 3. **Core** — built-in Cell modules ```javascript // From within package 'myapp': use('utils') // myapp/utils.cm use('helper/math') // myapp/helper/math.cm use('json') // core json module use('otherlib/foo') // dependency 'otherlib', file foo.cm ``` Files starting with underscore (`_helper.cm`) are private to the package. ## Example: Simple Actor System ```javascript // main.ce - Entry point var config = use('config') log.console("Starting application...") $start(function(worker) { $send(worker, {task: "process", data: [1, 2, 3]}) }, "worker") $delay(function() { log.console("Shutting down") $stop() }, 10) ``` ```javascript // worker.ce - Worker actor $receiver(function(msg, reply) { if (msg.task == "process") { var result = array(msg.data, x => x * 2) reply({result: result}) } }) ``` ```javascript // config.cm - Shared configuration return { debug: true, timeout: 30 } ```