콘텐츠로 이동
Developer Preview — APIs and language features may change before 1.0

Computation

이 콘텐츠는 아직 번역되지 않았습니다.

compute steps are the workhorse of mashin. They handle data transformation, calculation, formatting, and output construction. They use the mashin expression language (JavaScript-inspired) and are pure by construction: they cannot perform I/O, call external services, or access the network. This purity is not enforced by a sandbox. The capability simply does not exist.

compute <name>
<expression>

The expression body is evaluated and its result becomes the step’s output. The last expression is the return value:

compute greet
{greeting: "Hello, " + input.name + "!"}

Use compute when you need to:

  • Transform data from inputs or previous steps
  • Calculate values (totals, averages, scores)
  • Build the final output of a machine
  • Format or reshape data structures
  • Apply conditional logic with ternary expressions

Do not use compute for anything that requires external interaction. Use ask ... using for LLM reasoning. Use ask ... from for calling other machines. Use action for HTTP, database, or file operations.

Break complex expressions into readable steps with let:

compute analyze
let items = input.orders.filter(o => o.status == "completed")
let total = items.reduce((sum, o) => sum + o.amount, 0)
let count = items.length
let average = count > 0 ? total / count : 0
{
completed_count: count,
total_revenue: total,
average_order: average,
above_average: items.filter(o => o.amount > average).length
}

Each let binding is scoped to the current step.

Access results from earlier steps with steps.<name>.<field>:

machine pipeline
accepts
text as text, is required
responds with
label as text
score as number
summary as text
behaves
ask classify, using: "anthropic:claude-sonnet-4-6"
with task "Classify this text: ${input.text}"
returns
category as text
confidence as number
compute format
let label = steps.classify.category
let score = steps.classify.confidence
{
label: label,
score: score,
summary: label + " (confidence: " + score + ")"
}
verifies
test "formats the classification"
assuming classify {category: "technology", confidence: 0.92}
given {text: "New chip announced"}
expect {label: "technology", score: 0.92}

Use the ternary operator for inline conditionals:

compute categorize
let amount = input.amount
{
tier: amount > 10000 ? "enterprise" : amount > 1000 ? "business" : "starter",
needs_review: amount > 5000,
formatted: "$" + amount.toString()
}

For more complex branching, use a decide step instead. See Decisions.

compute combine_results
{
sentiment: steps.analyze_sentiment.label,
topics: steps.extract_topics.topics,
summary: steps.summarize.text,
processed_at: now()
}
compute filter_high_priority
let urgent = steps.classify.items.filter(i => i.priority == "urgent")
let names = urgent.map(i => i.name)
{
urgent_items: urgent,
urgent_names: names,
urgent_count: urgent.length
}
compute normalize
let cleaned = input.text.trim()
let words = cleaned.split(" ").filter(w => w.length > 0)
{
original: input.text,
cleaned: cleaned,
word_count: words.length,
preview: words.slice(0, 10).join(" ") + (words.length > 10 ? "..." : "")
}

Compute steps are pure by construction (Law I). They:

  • Never require governance approval
  • Never appear in permission checks
  • Always execute, regardless of trust level
  • Are safe to run in any mode (full, test, simulate)

This is why a machine with only compute steps does not need an ensures section. There is nothing to govern.

Write a machine that accepts a list of products (each with a name, price, and quantity). Use a single compute step to calculate the subtotal for each product, the overall total, the most expensive item, and the cheapest item. Use let bindings to keep the logic readable.