Values, types and f-strings
The first assignment creates a variable (x = 1); var makes one that changes. Types are inferred, so you rarely write them. f-strings format values into text, and {ratio:.2f} formats decimals. Division 10 / 4 produces 2.5; whole-number division is 10.div(4).
name = "Ada"
var visits = 1
visits += 1
ratio = 2.0 / 3.0
print(f"{name} has visited {visits} times")
print(f"ratio is {ratio:.2f}")
print(10 / 4, 10.div(4), 10 % 4, 2 ** 5)outputAda has visited 2 times ratio is 0.67 2.5 2 2 32
Lists, loops and comprehensions
A list is written [a, b, c]. for i, x in list gives the position and item. Negative indexes count from the end (fruits[-1]), and in tests membership. List comprehensions build new lists: [f.length for f in fruits]. 0..3 is a range, write prints without a newline, and sum and max are built in.
fruits = ["apple", "pear", "fig"]
for i, fruit in fruits {
print(f"{i + 1}. {fruit}")
}
print(f"last: {fruits[-1]}, pear in list: {\"pear\" in fruits}")
for n in 0..3 {
write(f"{n} ")
}
print("")
lengths = [f.length for f in fruits]
print(lengths)
print(sum(lengths), max(lengths))output1. apple 2. pear 3. fig last: fig, pear in list: true 0 1 2 [5, 4, 3] 12 5
Functions and expressions
Functions start with fn. Parameters have types (inferred when omitted), defaults, and optional labels at call sites: greet("Bo", times: 2). if c { a } else { b } is an expression, returning a value directly without ternary syntax.
fn greet(name: String, times: Int = 1) -> String {
var out = ""
for _ in 0..times { out += f"hi {name}! " }
return out
}
fn level(score: Int) -> String {
return if score >= 90 { "expert" } else if score >= 70 { "pro" } else { "novice" }
}
print(greet("Ada"))
print(greet("Bo", times: 2))
print(f"score 85 is {level(85)}")outputhi Ada! hi Bo! hi Bo! score 85 is pro
Values that may be missing
A type ending in ?, such as Int?, may be nil, and the compiler makes you deal with that before you use it. if let unwraps it and ?? supplies a fallback.
fn find(names: [String], wanted: String) -> Int? {
for i, n in names {
if n == wanted { return i }
}
return nil
}
names = ["ana", "bo", "chen"]
if let i = find(names, "bo") {
print(f"found at {i}")
}
print(find(names, "zed") ?? -1)outputfound at 1 -1
Enums and match
An enum lists the shapes a value can take, each with its own data. match picks the matching case and binds the data. It must cover every case. Leave one out and the program does not run (second example).
enum Shape { Circle(r: Float), Rect(w: Float, h: Float) }
fn area(s: Shape) -> Float {
return match s {
.Circle(r) => 3.14159 * r * r
.Rect(w, h) => w * h
}
}
print(f"{area(Shape.Rect(w: 2.0, h: 3.0)):.2f}")output6.00
enum Shape { Circle(r: Float), Rect(w: Float, h: Float) }
fn area(s: Shape) -> Float {
return match s {
.Circle(r) => 3.14159 * r * r
}
}compiler sayserror [E0460]: this match does not cover every case
--> missing_case.myc:4:10
|
4 | return match s {
| ^^^^^^^^^
why: not handled: Shape.Rect(_, _)
fix: add arms for Shape.Rect(_, _), or a catch-all `_ => ...`
1 error, 0 warningsClasses
A class holds fields and methods. Create one by calling its name, with no new, and reach its own fields through self.
class Account {
var balance = 0
fn deposit(amount: Int) {
self.balance += amount
}
}
acct = Account()
acct.deposit(50)
acct.deposit(25)
print(f"balance: {acct.balance}")outputbalance: 75
Errors you can see in the type
A function that can fail returns Result<Ok type, Error type>. Return Ok(value) or Err(reason), and put ? after a call to pass an error straight up to the caller.
fn parseAge(text: String) -> Result<Int, String> {
n = Int.parse(text)
if n == nil { return Err(f"'{text}' is not a number") }
return Ok(n!)
}
fn nextYear(text: String) -> Result<Int, String> {
age = parseAge(text)?
return Ok(age + 1)
}
print(nextYear("41"))
print(nextYear("forty"))outputOk(42)
Err("'forty' is not a number")Web apps with std.web
Mycel includes std.web for web applications: routes with :params, HTML rendering, JSON APIs, and form handling. In production, app.run(8000) serves until stopped (needs --allow-listen).
import std.web
import std.http
var messages = ["Hello from Mycel!"]
app = web.App()
app.get("/", req => {
items = [f"<li>{web.escape(m)}</li>" for m in messages].join("")
return web.html(f"<h1>Guestbook</h1><ul>{items}</ul>")
})
app.post("/sign", req => {
text = req.form.get("message", "").trim()
if text.isEmpty { return web.text("write something first", status: 422) }
messages.push(text)
return web.redirect("/")
})
app.get("/messages.json", req => web.json({"count": len(messages), "items": messages}))
// In production: app.run(8000) serves on port 8000
// Test live over HTTP:
server = (await app.start(0)).unwrap()
base = f"http://127.0.0.1:{server.port}"
print((await http.get(base + "/")).unwrap().body)
print((await http.get(base + "/messages.json")).unwrap().body)
server.stop()output<h1>Guestbook</h1><ul><li>Hello from Mycel!</li></ul>
{"count":1,"items":["Hello from Mycel!"]}Mistakes are caught before the program runs
Types are checked up front. The compiler tells you what went wrong, where, and why, and usually how to fix it. Habits from other languages get the same treatment: see the guides for Python, JavaScript and TypeScript, Java, Go, Rust and Swift.
let age: Int = "fifteen" print(age)compiler says
error [E0300]: type mismatch: expected Int, found String --> mistake.myc:1:16 | 1 | let age: Int = "fifteen" | ^^^^^^^^^ why: the initial value has type String, but Int is required here 1 error, 0 warnings
Programs start with no permissions
A Mycel program with no permissions is pure: it can compute and print, nothing else. Files, network, processes and environment variables are capabilities the host grants for each run (for example mycel run app.myc --allow-read=data), never assumed. That is why the playground can run anyone's code safely.
What works, and what doesn't yet
Mycel is in development and not released: there is nothing to download or install today, so the playground is the way to try it. Every example on this page was run with the current compiler and the output shown is exactly what it printed. Details will change. A compatibility engine for Python, JavaScript/TypeScript, Java, Rust, Go and Swift packages is planned; installing foreign packages is not available yet. Files use .myc (.olx also works).
Where to go from here
Read the guide for the language you already know, go back to the Mycel overview, or explore our fine-tuning datasets and materials for AI models.