Synsema docsENES

Python → Synsema — the translation table

You (an LLM, or a Python developer) already know Python. This page maps the Python reflex

to the Synsema form and flags exactly where the semantics diverge. It is faster than

learning from scratch, and it prevents the classic failure mode: writing Python with

Synsema keywords.

**The one rule that prevents most hallucinations: if you did not see it in these docs, it

does not exist.** There is no import, no Python stdlib, no classes, no comprehensions,

no decorators, no with, no generators, no method-call syntax on values

(xs.append(x) → builtins are plain tasks: append(xs, x)).

Every semantic claim below is asserted by this passing doctest:

python-diff.syn
-- Doc example: the Python → Synsema divergences that bite the hardest.
-- Every claim in the translation-table page is asserted here (doctested).
intent: "doc example: python-to-synsema translation table"

task boom()
    raise("kaput")

task reraise_error()
    try
        boom()
    recover err
        raise(err)

task bad_return()
    return 5

task give_none()
    give None

task iterate_map_directly()
    each k in {"a": 1}
        print(k)

test "assignment is let/set, not = (x = 5 is a parse error)"
    let x be 1
    set x to 2
    assert_eq(x, 2)

test "Python 'return'/'None'/'True' PARSE but are undefined names — use give/nothing/true"
    assert_error(bad_return)
    assert_error(give_none)
    assert_eq(nothing == nothing, true)

test "try/recover (not try/except); recover SWALLOWS unless you raise(err)"
    let seen be ""
    try
        boom()
    recover err
        set seen to err
    assert(contains(seen, "kaput"))
    assert_error(reraise_error)

test "and/or do NOT short-circuit — guard with nested when, not with `and`"
    let m be {"a": 1}
    assert_error(() => contains(m, "b") and m["b"] == 1)
    when contains(m, "a")
        assert_eq(m["a"], 1)

test "append returns a NEW list (no mutating .append); reassign with set"
    let xs be [1, 2]
    let ys be append(xs, 3)
    assert_eq(xs, [1, 2])
    assert_eq(ys, [1, 2, 3])

test "f-string equivalent is the backtick string; quoted strings stay literal"
    assert_eq(`n={1 + 1}`, "n=2")
    assert(contains("n={1+1}", "{"))

test "each cannot iterate a map — go through keys()"
    assert_error(iterate_map_directly)
    let ks be []
    each k in keys({"x": 1, "y": 2})
        set ks to append(ks, k)
    assert_eq(ks, ["x", "y"])

test "comprehension equivalent: apply + where; slicing is slice()"
    assert_eq(apply((x) => x * 2, where([1, 2, 3], (x) => x > 1)), [4, 6])
    assert_eq(slice([10, 20, 30, 40], 1, 3), [20, 30])
    assert_eq(slice([10, 20, 30, 40], -2, 4), [30, 40])

test "the `in` operator is contains(); on maps it checks KEYS"
    assert(contains([1, 2], 2))
    assert(contains("abc", "b"))
    assert(contains({"a": 1}, "a"))

test "text + number CONCATENATES (unlike Python); text * n does not exist"
    assert_eq("a" + 1, "a1")
    assert_error(() => "ab" * 2)

test "len/str/sorted are length/text/sort_by; d.get(k, default) does not exist"
    assert_eq(length("abc"), 3)
    assert_eq(text(42), "42")
    assert_eq(sort_by([3, 1, 2], (x) => x), [1, 2, 3])
    assert_error(() => get({"a": 1}, "a"))
    assert_error(() => {"a": 1}["b"])

Syntax reflexes

In PythonIn Synsema⚠️ Divergence
x = 5x = 6let x be 5set x to 6x = 5 → parse error Unexpected token: ASSIGN ('='). = exists ONLY in default params / named args: task f(x, y = 1), f(x, y = 2)
# comment-- comment#Unexpected character: '#'
if / elif / else:when / otherwise when / otherwise (no colon)a trailing : → parse error; elif is not a word
x if c else ywhen c then x otherwise yinline expression form, usable in let/args
for x in xs:each x in xsfor → parse error
for k in a_dict:each k in keys(m)each cannot iterate a map: Cannot iterate over map. Go through keys(m)/values(m)
for i, x in enumerate(xs):each i in range(length(xs))xs[i]no enumerate
while c:while csame keyword, no colon; runaway loops hit Loop exceeded maximum iterations
def f(x): return vtask f(x)give vdef → parse error. return PARSES as a plain name, then fails at runtime: Undefined variable: 'return' — the word is give
lambda x: x + 1(x) => x + 1
None / True / Falsenothing / true / falsecapitalized forms parse, then fail: Undefined variable: 'None' (same for True/False)
x is Nonex == nothingno is operator for identity (is belongs to match)
f"n={n}"` n={n} ` (backtick string)f"..." → parse error. Quoted "..." strings do NOT interpolate ("{n}" stays literal) and a literal newline inside them is Unterminated string — backticks do both
"""multi-line"""` multi-line `backticks allow real newlines + {expr}
[f(x) for x in xs if p(x)]apply(f, where(xs, p))comprehension syntax → parse error
xs[1:3], xs[-2:]slice(xs, 1, 3), slice(xs, -2, length(xs))[1:3] → parse error; slice takes Python-style negatives, works on lists/text/bytes
x in xs (operator)contains(xs, x)in is only valid inside each. On maps contains checks KEYS
try/except E as e:tryrecover errexcept → parse error. err is the message TEXT (no exception types/hierarchy). recover SWALLOWS by default — re-propagate with raise(err)
raise ValueError("x")raise("x") (or statement raise "x")one error kind only; on engine ≤ v0.5.1 use the parens form
import json, import requestsnothing to import — builtins are globalimport x parses as a name and fails: Undefined variable: 'import'. JSON/HTTP/etc. are builtins gated by capabilities (below)
from mymodule import fuse "./mymodule.syn" as mm.f()only local .syn modules; exports need exportModules
class Person:type Person (fields) + plain tasksno methods/inheritance/self; construct Person("Alice", 30), access p.name / name of p / p["name"]
match/casematchis patternarms use is, default is otherwiseSyntax

Also: the LLM words **reason / decide / analyze / generate are reserved

everywhere** (even as member/param names) — let reason be 1 → `'reason' is a reserved

word in Synsema. Name things resolve, why`, etc.

Builtin equivalents (methods are plain tasks)

In PythonIn Synsema
len(x)length(x) (text/list/map/bytes/array)
str(x) / int(s) / float(s)text(x) / number(s) (always float; floor() to get an integer)
xs.append(x) (mutates)append(xs, x)returns a NEW list; reassign: set xs to append(xs, x)
s.upper() / s.lower() / s.strip()upper(s) / lower(s) / trim(s)
s.split(",") / ",".join(xs)split(s, ",") / join(xs, ",")
s.startswith(p) / s.replace(a, b)starts_with(s, p) / replace_text(s, a, b)
sorted(xs, key=f) / reverse=Truesort_by(xs, f) / sort_by(xs, (x) => 0 - x) (no bare sort)
sum(xs) / min(xs) / max(xs)sum(xs) / min(xs) / max(xs) (also variadic max(a, b, c))
map(f, xs) / filter(p, xs)apply(f, xs) / where(xs, p) — both accept either argument order
functools.reduce(f, xs, init)reduce(xs, f, init)
xs.index(v) (raises) / v in xsindex_of(xs, v)nothing when absent (not -1, no error)
d.get(k, default)does not exist — when contains(m, "k") then index (nested when, see traps)
d.keys() / d.values() / d.items()keys(m) / values(m) / no items — iterate keys(m) and index
json.dumps(x) / json.loads(s)json_encode(x) / json_decode(s) (pure, no import) — JSON
range(n)range(n) → a real list (also range(a, b, step))
print(...)print(...) (buffered under run until exit — flush() for live output)
re.fullmatch / re.findallmatches(s, pat) (FULL match) / find_all(s, pat)Builtins
open(p).read() / requests.get(url)read_file(p) + require file(...) / fetch(url) + require net(host)Files, HTTP

Semantic traps — looks like Python, behaves differently

It looks likeWhat actually happens (doctested above)
a and b short-circuitsNO short-circuit — both sides ALWAYS evaluate. contains(m, "k") and m["k"] == 1 still errors Map has no key 'k' when the key is absent. Guard with nested when instead
xs.append mutates in placeappend (and friends) return new values; the original is untouched. Reassign with set
d["missing"] → KeyError you catch by typeMap has no key 'missing' — catchable only as try/recover (message text)
"a" + 1 → TypeErrorIt concatenates: "a" + 1"a1" (text + number coerces). But "ab" * 2 and 1 + true ARE errors — no repetition, no bool arithmetic
except: keeps the program dyingrecover swallows the error entirely (task ends normally). To fail upward, raise(err) inside recover
iterating a dict yields keyseach over a map is an ERROR — use keys(m)

More traps (also engine-verified): Counter your priors

and Errors & exit codes.

Where Python intuition is SAFE (verified — trust it)

No Python equivalent — read the topic page before using

db(...) / serve(PORT) / llm at the top or calls fail → Capabilities

parallel_mapMulti-agent