Synsema docsENES

Python → Synsema — la tabla de traducción

Vos (un LLM, o un dev de Python) ya sabés Python. Esta página mapea el reflejo de Python a

la forma Synsema y marca exactamente dónde diverge la semántica. Es más rápido que aprender

de cero, y previene el modo de falla clásico: escribir Python con keywords de Synsema.

**La regla que previene la mayoría de las alucinaciones: si no lo viste en estas docs, no

existe.** No hay import, no hay stdlib de Python, no hay clases, no hay comprehensions,

no hay decoradores, no hay with, no hay generadores, no hay sintaxis de método sobre

valores (xs.append(x) → los builtins son tasks planas: append(xs, x)).

Cada afirmación semántica de abajo está asegurada por este doctest que pasa:

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"])

Reflejos de sintaxis

En PythonEn Synsema⚠️ Divergencia
x = 5x = 6let x be 5set x to 6x = 5 → error de parseo Unexpected token: ASSIGN ('='). = existe SOLO en params con default / args nombrados: task f(x, y = 1), f(x, y = 2)
# comentario-- comentario#Unexpected character: '#'
if / elif / else:when / otherwise when / otherwise (sin dos puntos)un : al final → error de parseo; elif no es una palabra
x if c else ywhen c then x otherwise yforma expresión inline, usable en let/args
for x in xs:each x in xsfor → error de parseo
for k in un_dict:each k in keys(m)each no puede iterar un map: Cannot iterate over map. Pasá por keys(m)/values(m)
for i, x in enumerate(xs):each i in range(length(xs))xs[i]no hay enumerate
while c:while cmismo keyword, sin dos puntos; un loop desbocado corta con Loop exceeded maximum iterations
def f(x): return vtask f(x)give vdef → error de parseo. return PARSEA como un nombre y falla en runtime: Undefined variable: 'return' — la palabra es give
lambda x: x + 1(x) => x + 1
None / True / Falsenothing / true / falselas formas con mayúscula parsean y después fallan: Undefined variable: 'None' (igual True/False)
x is Nonex == nothingno hay operador is de identidad (is es de match)
f"n={n}"` n={n} ` (string con backticks)f"..." → error de parseo. Las strings con comillas "..." NO interpolan ("{n}" queda literal) y un newline literal adentro es Unterminated string — los backticks hacen ambas cosas
"""multilínea"""` multilínea `los backticks permiten newlines reales + {expr}
[f(x) for x in xs if p(x)]apply(f, where(xs, p))la sintaxis de comprehension → error de parseo
xs[1:3], xs[-2:]slice(xs, 1, 3), slice(xs, -2, length(xs))[1:3] → error de parseo; slice acepta negativos estilo Python, funciona en listas/text/bytes
x in xs (operador)contains(xs, x)in solo vale dentro de each. En maps contains chequea CLAVES
try/except E as e:tryrecover errexcept → error de parseo. err es el TEXTO del mensaje (no hay tipos/jerarquía de excepciones). recover TRAGA por defecto — re-propagá con raise(err)
raise ValueError("x")raise("x") (o la sentencia raise "x")un solo tipo de error; en engine ≤ v0.5.1 usá la forma con paréntesis
import json, import requestsnada que importar — los builtins son globalesimport x parsea como un nombre y falla: Undefined variable: 'import'. JSON/HTTP/etc. son builtins gateados por capabilities (abajo)
from mimodulo import fuse "./mimodulo.syn" as mm.f()solo módulos .syn locales; los exports necesitan exportMódulos
class Person:type Person (campos) + tasks planassin métodos/herencia/self; construí Person("Alice", 30), accedé p.name / name of p / p["name"]
match/casematchis patrónlos brazos usan is, el default es otherwiseSintaxis

Además: las palabras LLM **reason / decide / analyze / generate son reservadas en

todas partes** (incluso como nombres de member/param) — let reason be 1 → `'reason' is a

reserved word in Synsema. Nombrá las cosas resolve, why`, etc.

Equivalentes de builtins (los métodos son tasks planas)

En PythonEn Synsema
len(x)length(x) (text/list/map/bytes/array)
str(x) / int(s) / float(s)text(x) / number(s) (siempre float; floor() para entero)
xs.append(x) (muta)append(xs, x)devuelve una lista NUEVA; reasigná: 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 hay sort pelado)
sum(xs) / min(xs) / max(xs)sum(xs) / min(xs) / max(xs) (también variádico max(a, b, c))
map(f, xs) / filter(p, xs)apply(f, xs) / where(xs, p) — ambos aceptan cualquiera de los dos órdenes
functools.reduce(f, xs, init)reduce(xs, f, init)
xs.index(v) (lanza) / v in xsindex_of(xs, v)nothing si no está (no -1, no error)
d.get(k, default)no existe — when contains(m, "k") y después indexá (when anidado, ver trampas)
d.keys() / d.values() / d.items()keys(m) / values(m) / no hay items — iterá keys(m) e indexá
json.dumps(x) / json.loads(s)json_encode(x) / json_decode(s) (puros, sin import) — JSON
range(n)range(n) → una lista real (también range(a, b, paso))
print(...)print(...) (bufferea bajo run hasta salir — flush() para salida en vivo)
re.fullmatch / re.findallmatches(s, pat) (match COMPLETO) / find_all(s, pat)Builtins
open(p).read() / requests.get(url)read_file(p) + require file(...) / fetch(url) + require net(host)Archivos, HTTP

Trampas semánticas — parece Python, se comporta distinto

Parece queLo que pasa en realidad (doctesteado arriba)
a and b cortocircuitaNO cortocircuita — ambos lados se evalúan SIEMPRE. contains(m, "k") and m["k"] == 1 igual falla con Map has no key 'k' cuando la clave no está. Guardá con when anidado
xs.append muta in placeappend (y familia) devuelven valores nuevos; el original queda intacto. Reasigná con set
d["missing"] → KeyError que atrapás por tipoMap has no key 'missing' — atrapable solo como try/recover (texto del mensaje)
"a" + 1 → TypeErrorConcatena: "a" + 1"a1" (text + number coerciona). Pero "ab" * 2 y 1 + true SÍ son errores — no hay repetición ni aritmética de bools
except: deja el programa muriendorecover traga el error entero (la task termina normal). Para fallar hacia arriba, raise(err) dentro de recover
iterar un dict da las claveseach sobre un map es ERROR — usá keys(m)

Más trampas (también verificadas contra el engine): Contra tus instintos

y Errores y exit codes.

Dónde tu intuición de Python SÍ es segura (verificado — confiá)

Sin equivalente en Python — leé la página del tema antes de usar

db(...) / serve(PUERTO) / llm arriba o las llamadas fallan → Capabilities

parallel_mapMulti-agente