olix / Mycel / Python developers
in development

Mycel for Python developers

If you write Python, most of Mycel will already look familiar. It keeps the parts of Python that make it easy to read — f-strings, x = 1, list comprehensions, x in items, xs[-1], d.get(), Set — and adds static types that are inferred, so mistakes are caught before anything runs.

Try Mycel in your browser →

Same

Much of what you type already works

These Python spellings are valid Mycel as they are: and / or / not, print(a, b), f-strings (with {x:.2f} and {x=}), for i, x in items, len(x), x ** 2, variable assignment x = 1 without let, tuple swaps a, b = b, a, list comprehensions [x * 2 for x in xs if x > 1], negative indexes xs[-1], dict lookup d.get(k, default), set operations & | - on Set([1, 2]), x if c else y expressions, and a file that is just statements with no main().

tour_python.mycvalid Python spellings, running as Mycel · open in playground
names = ["ana", "bo", "chen"]
for i, name in names {
  print(f"{i}: {name}")
}

a, b = 1, 2
a, b = b, a
squares = [x ** 2 for x in [1, 2, 3, 4] if x > 1]
counts = {"a": 10}
tags = Set(["py", "myc"]) & Set(["myc", "fast"])
status = "ok" if "bo" in names else "missing"

print(len(names), "names", f"last={names[-1]}", f"swapped=({a}, {b})")
print(f"squares={squares}, get={counts.get(\"z\", 0)}, tags={tags.sorted()}, status={status}")
output
0: ana
1: bo
2: chen
3 names last=chen swapped=(2, 1)
squares=[4, 9, 16], get=0, tags=["myc"], status=ok
Different

What is different

  • Blocks use braces { ... }, not a trailing colon and indentation.
  • Functions are fn name(args) { ... }; def is rejected with an error that says so.
  • else if instead of elif; nil instead of None; true / false in lower case; throw and catch e { ... } instead of raise and except; x => x + 1 instead of lambda.
  • Conditional expressions: both if c { a } else { b } (Rust/Swift/Kotlin) and Python's a if c else b work.
  • Types are static and inferred. Mismatches are reported before anything runs, so a wrong type never reaches a half-finished program.
  • Numbers mix like Python: n * 1.5 yields a Float, 10 / 4 produces 2.5, and whole-number integer division is 10.div(4).
numbers.mycdivision and mixed numbers · open in playground
n = 10
print(n / 4, n.div(4), n % 4)
print(n * 1.5)
output
2.5 2 2
15.0
types.mycreported before the program runs · open in playground
let age: Int = "fifteen"
print(age)
compiler says
error [E0300]: type mismatch: expected Int, found String
  --> types.myc:1:16
  |
1 | let age: Int = "fifteen"
  |                ^^^^^^^^^
  why: the initial value has type String, but Int is required here

1 error, 0 warnings
Habit fix-its

Every Python habit and what Mycel says

Mycel's compiler recognises words and symbols from other languages. Instead of a generic syntax error you get the language it came from and the Mycel spelling. The full list for Python is below; rows marked works are valid Mycel as you already write them.

habit.myca Python habit gets a fix, not a puzzle · open in playground
def greet(name):
  print(name)
compiler says
error [E0101]: `def` is Python — Mycel writes `fn name(args) { ... }`
  --> habit.myc:1:1
  |
1 | def greet(name):
  | ^^^
  why: this word comes from another language
  fix: see `mycel help habits`

1 error, 0 warnings
You writeMycel says
and / or / notworks: and, or, not work (same as && || !)
print(a, b)works: prints the values with a space between
f"hi {name}"works: the same: f-strings with {x:.2f} and {x=}
for i, x in itemsworks: the same
len(x)works: the same
x ** 2works: the same
no main(): statements at the topworks: the same: a file can just be statements
x if c else yworks: the same
x = 1 (no let)works: the same: the first assignment creates the variable
a, b = b, aworks: the same
x in items / not inworks: the same
[x * 2 for x in xs if x > 1]works: the same
xs[-1]works: the same: negative indexes count from the end
d.get(k, default)works: the same
a & b, a | b, a - b on setsworks: the same; sets are written Set([1, 2])
def f(x):def is Python — Mycel writes fn f(x) { ... }
elifelif is Python — Mycel writes else if
NoneNone is Python — Mycel writes nil
True / FalseTrue/False are Python — Mycel writes true / false
if x:a : block is Python — Mycel blocks use { ... }
lambda x: x + 1lambda is Python — Mycel writes x => x + 1
raiseraise is Python — Mycel writes throw
exceptexcept is Python — Mycel writes catch e { ... }

Every row is tested in the compiler, and mycel help habits prints the same list. See also the overview on the Mycel page.

Packages

Using Python packages: planned (coming in Phase B)

A compatibility engine so a Mycel program can use Python packages is planned, and the package manager ply already recognises the install flags. The planned form is ply install --py requests. Installing packages from other languages is marked as coming until Phase B lands, and Mycel itself is not released: there is nothing to download yet. The playground runs the real compiler in your browser with no packages.

Try it

Run the first example yourself

The Mycel playground opens in your browser. It runs the real compiler in a sandbox with no file, network or storage access, and nothing is sent to a server. For a guided walk through the language, read Learn Mycel.

More

Other starting points

Mycel is written so a program reads the same whichever language you learned first. Pick the guide closest to yours, or take the full tour.