{"path":"/sutl/history/portable-computation","content":{"title":"Portable computation and active data","summary":"Part of the sUTL history essay, with current release notes distinguishing shipped behavior from future ideas.","body":"[sUTL](/sutl) · [Guide](/sutl/guide) · [Reference](/sutl/reference) · [Examples](/sutl/examples)\n\nThis essay records the history and design direction of sUTL. Since the original reconstruction, sUTL 1.0 and JavaScript, Python and Go packages have been released. Implementation releases from 1.1.0 support step/depth limits and cancellation. Compiler and native-code-generation ideas below remain proposals. See [the current reference](/sutl/reference) and [sUTL in Everything](/sutl/everything).\n\n## Why the idea still seems useful\n\nWhen I originally described sUTL as a transformation language, the obvious comparison was to templating and JSON manipulation tools.\n\nToday I would describe its strongest use case somewhat differently.\n\nsUTL is potentially a **portable, deterministic, [capability-safe](https://en.wikipedia.org/wiki/Capability-based_security) computation language for structured values**.\n\nThat is useful anywhere a system would like to accept computation from another party without accepting arbitrary executable code.\n\nConsider an API returning large records.\n\nA conventional endpoint may support projection:\n\n```text\nGET /customers?fields=id,name,email\n```\n\nBut projection only selects fields.\n\nInstead, the endpoint could accept an sUTL transform and apply it to each record before returning anything.\n\nThe caller could reshape nested structures, calculate values, normalize data, extract selected descendants or construct an entirely different result.\n\nThe computation occurs near the data, so the service need not transmit a huge record when the caller only needs a small derived value.\n\nYet the caller has not been allowed to upload arbitrary JavaScript or Python.\n\nThe transform can only compute from values it has been given.\n\nThis is **safe computation pushdown**.\n\nIt is particularly attractive for agents. An agent receiving a 200 KB API response may only need a 2 KB derived structure. Rather than transferring everything and spending model tokens interpreting it, the agent could construct a small transform and ask the service to execute it locally.\n\nThe same idea applies to stored transformations.\n\nA pipeline service might allow a caller to upload and persist a transform:\n\n```text\nincoming record\n      ↓\nstored transform A\n      ↓\nstored transform B\n      ↓\ndestination\n```\n\nThe stored stages are executable, but they are not arbitrary foreign code.\n\nBecause they are pure transformations over MLSNBN, the runtime does not need to give them filesystem access, sockets, environment variables, process creation, credentials or reflection.\n\nThey can be versioned as data, replayed against historical inputs and moved between compatible runtimes.\n\nThat is a much smaller security problem than hosting general-purpose scripts.\n\n## Active data\n\nThere is a related idea that I find even more interesting now.\n\nInstead of storing only a value, a system can store a transform that **evaluates to that value**.\n\nLiteral data is then simply the trivial case of a transform.\n\nMore interesting stored values can contain derived structure:\n\n```text\nplain data\n    ↓\ndata with calculated pieces\n    ↓\nparameterised document\n    ↓\ntransformation template\n    ↓\nfull computation\n```\n\nA configuration document could be a transform that evaluates against an environment to produce concrete configuration.\n\nA stored customer \"view\" could be a transform evaluated against raw customer data.\n\nAn API representation could be stored as a transformation rather than as duplicated materialized data.\n\nAn invoice definition could be a transform that produces an invoice value from its context.\n\nBecause the program is itself MLSNBN, all of these definitions remain ordinary structured values at rest.\n\nThis is something Lisp made conceptually natural, but MLSNBN makes unusually interoperable.\n\n## Purity should remain non-negotiable\n\nOne temptation would be to make sUTL more useful by adding impure builtins:\n\n```text\nhttp_get\nread_file\ndatabase_query\nnow\nrandom\n```\n\nI think that would destroy one of its best properties.\n\nThe useful invariant is:\n\n> **A sUTL transform cannot do anything except compute a value from values it has been given.**\n\nThat does not mean a larger system built around sUTL cannot perform effects.\n\nThe right model is much closer to a modern [LLM tool harness](https://en.wikipedia.org/wiki/Large_language_model).\n\nIf a program needs an HTTP operation, the transform can emit an MLSNBN value *describing* the requested operation:\n\n```json\n{\n  \"$effect\": \"http\",\n  \"args\": {\n    \"method\": \"GET\",\n    \"url\": \"https://example.com/customer/123\"\n  }\n}\n```\n\nThe sUTL evaluator has still done nothing impure.\n\nAn external harness can inspect that value, decide whether the operation is allowed, apply authentication and policy, execute it, and pass the MLSNBN result into the next transform.\n\nThe execution model becomes:\n\n```text\ninput\n  ↓\npure sUTL\n  ↓\neffect description\n  ↓\nexternal harness\n  ↓\neffect result\n  ↓\npure sUTL\n```\n\nThis cleanly separates **describing an effect** from **having authority to perform one**.\n\nThe same transform can therefore run under a test harness, a browser harness, a locked-down server harness or an agent harness with different effect policies.\n\nEffects remain inspectable, auditable and replayable.\n\nsUTL stays pure.\n\n## Turing completeness and resource safety\n\nPurity gives strong capability safety, but it does not by itself solve resource safety.\n\nA Turing-complete transform can still loop forever, recurse excessively, traverse large structures repeatedly or construct enormous intermediate results.\n\nA modern runtime should therefore be **metered**.\n\nThe natural model is fuel or another deterministic execution budget.\n\nFor example, an execution environment might enforce limits on:\n\n```text\nevaluation steps\nrecursion depth\nintermediate allocation\noutput size\nwall-clock time\n```\n\nEvery operation consumes some amount of budget. When the budget is exhausted, evaluation terminates with a resource-limit result.\n\nThis is a much simpler security boundary than trying to sandbox arbitrary JavaScript.\n\nIt also preserves the lesson learned from bOTL.\n\nThe answer to computational complexity was not to cripple the language until difficult transformations became impossible. It was to make the language expressive, then control the execution environment explicitly.\n\n## Read the essay\n\n[From bOTL to sUTL](/sutl/history/origins) · [Portable computation and active data](/sutl/history/portable-computation) · [Compilation and the future of sUTL](/sutl/history/future)\n\n## Source\n\nAdapted from [the sUTL source material](https://github.com/emlynoregan/sutllang-site/blob/e59ecafd364848cd71a1d18ce74cdf67f2f69328/content/essay.md).\n\n[Back to sUTL](/sutl) · [Software & Agents](/topics/software-and-agents) · [All topics](/guide)","author":"Emlyn O'Regan"}}