C++ with the simplicity of Python

seadash is a language that looks like Python and runs like C++. You write Python's syntax, the compiler checks the whole program's types, translates it to C++23, and builds a native binary.

books.sd
from collections import Counter
from dataclasses import dataclass


@dataclass
class Book:
    title: str
    words: list[str]

    @property
    def longest(self) -> str:
        return max(self.words, key=len)


def find(books: list[Book], title: str) -> Book | None:
    for b in books:
        if b.title == title:
            return b
    return None


books = [
    Book("sea", "the sea the sea is calm".split()),
    Book("dash", "dash off a quick note".split()),
]
counts = Counter(w for b in books for w in b.words)
print(counts.most_common(2))

book = find(books, "dash")
if book is not None:  # book is Book? until checked
    print(f"{book.title}: {len(book.words)} words, longest is {repr(book.longest)}")
terminal
$ sd run books.sd
[('the', 2), ('sea', 2)]
dash: 5 words, longest is 'quick'
$ python3 books.sd    # the same program, the same output
[('the', 2), ('sea', 2)]
dash: 5 words, longest is 'quick'

Familiar

Indentation, slicing, f-strings, comprehensions, generators, match, dataclasses, import json. Most small Python programs are valid seadash, and many of its test programs run unchanged under python3.

Checked

Types are inferred and checked before anything runs. None can't sneak into a str: T | None must be checked first, and the checker narrows it. Errors say what's wrong and how to fix it.

Threads without a GIL

Real OS threads in parallel, checked for data races when compiling. Threads get copies, or share through Mutex, queue.Queue, Atomic and Synchronized classes.

Fast

No interpreter: typical programs run 7–70× faster than CPython. The compiler is plain Python, the runtime a header-only C++ library, and builds are cached.

Benchmarks

Each runs unchanged under python3 and seadash, with identical output (best of 3).

benchmarkpython3seadashspeedup
objects classes, virtual methods, floats, recursion2.52s0.04s67×
queue_batches a producer thread sending big batches through a queue3.53s0.09s41×
threads parallel CPU work, queues, locks7.49s0.20s37×
particles a value class holding a list, rebuilt every step1.67s0.16s10×
lists_dicts building and querying lists and dicts2.10s0.29s7.2×
small_lists many small lists, merge sort, dicts of lists2.66s0.47s5.7×
hashing hashlib and hmac (time spent in OpenSSL)1.22s0.89s1.4×
json_load json.loads (native code in both)3.24s3.28s1.0×

The language

  • Static types, inferred. Annotate parameters; locals are worked out. A name can be rebound to a new type.
  • @value classes are copied on assignment, lists and all; other classes, lists and dicts are shared references, as in Python.
  • Typed JSON. users: list[User] = json.loads(text) decodes straight into your dataclasses.
  • Generators are C++20 coroutines; map, zip, itertools and generator expressions are lazy.
  • Unpacking and the rest: first, *rest = xs, f(*args), keyword-only parameters, del, slice assignment, closures, decorators, generics.

Standard library

argparse · base64 · bisect · bz2 · collections · concurrent.futures · contextlib · copy · csv · dataclasses · datetime · enum · errno · fnmatch · functools · glob · gzip · hashlib · heapq · hmac · html · http.client · http.server · itertools · json · logging · lzma · math · mimetypes · os · pathlib · queue · random · re · secrets · shlex · shutil · socket · sqlite3 · ssl · stat · statistics · string · struct · subprocess · sys · tempfile · textwrap · threading · time · urllib · uuid · zlib · zoneinfo

Each follows Python's API, output and error messages; where seadash differs, the README says so.

Examples

All examples, each with its source and a run.

Using it

terminal
$ sd run prog.sd [args]     # compile (cached) and run
$ sd check prog.sd          # type-check; list every variable's inferred type
$ sd build prog.sd -o prog  # a native binary, built with -O3
$ sd emit prog.sd           # the generated C++
$ echo 'print(sum(x * x for x in range(10)))' | sd run
285

Needs Python 3.12+, g++ 14 on Linux or Apple clang on macOS, and the zlib, PCRE2 and OpenSSL headers.