Four foundations, one language.
Quaryn treats safety, authority, portability, and performance as properties of one language rather than reasons to switch languages.
Quaryn takes the parts people love from Rust, Go, Python, and JavaScript and folds them into one clean design -- the safety of Rust without the headache, the speed of Go, the easy feel of Python, and JavaScript's natural fit with JSON.
Every programming language makes a trade. Some are fast but hard (Rust). Some are easy but slower (Python). Quaryn's whole reason to exist is to refuse that trade -- to be easy to read and hard to crash at the same time.
The one-sentence version: Quaryn catches whole families of bugs before your program ever runs -- the kind that crash apps or leak memory -- but it does it without the confusing symbols and ceremony that make languages like Rust intimidating.
For a non-programmer: imagine a word processor that won't let you save a document with a broken sentence in it. Quaryn is like that for code -- it reads your program first, points at the exact spot something would go wrong, and only lets it run once it's sound.
Here is Quaryn's signature -- the mark that makes a
.qry file unmistakable. A Quaryn program opens by stating, in
brackets, exactly what it's allowed to touch: the network, the file
system, and so on. And it isn't a comment or a suggestion -- the compiler
enforces it.
It says what it needs…
uses [net, threads] fn main() { spawn(() => serve(8080)) }
…or it simply won't run
// forgot to declare it? fn main() { http_get(url) } error: `http_get` needs network access, but this file does not declare it → add `uses [net]` at the top
uses [net]? You know it phones home before you
run a single line. It's a security label baked into the language -- and it
doubles as Quaryn's fingerprint.
You can spot Python by its indentation, JavaScript by its
const and arrows. Here are the tells that make a
.qry file unmistakably Quaryn -- each one shown in real code.
It uses {} like Go or Rust, but the noise is stripped out
-- no semicolons required, type names read like English.
fn greet(name: String) -> String { f"Hello, {name}!" }
Values are locked by default. You write let mut only when
you truly want something to change -- so accidental edits become
impossible.
let total = 42 // fixed forever let mut count = 0 // this one may change count = count + 1
The billion-dollar mistake -- the empty value that crashes apps
everywhere -- simply doesn't exist. Missing things are
Option, failures are Result, and the
? passes errors up cleanly.
fn load(url: String) -> Result<String, String> { let resp = http_get(url)? // if it fails, stop here neatly Ok(resp.body) }
The match keyword forces you to answer for every
possibility. Forget one, and Quaryn refuses to run -- no silent gaps.
match state { State::Idle => println("waiting"), State::Running(t) => println(f"tick {t}"), State::Done(msg) => println(msg), }
Born for the web. Turn a web response straight into your own typed data in one line -- no libraries to wire up.
let order: Result<CreateOrder, String> = req.body.json_decode()
The pipe |> reads like a sentence: take this, then do
that, then that.
let line = names |> map(n => n.shout()) |> join(", ")
Rust is famously safe, but it asks you to learn "lifetimes" -- a web of symbols that scares newcomers away. Quaryn keeps the safety and throws the symbols in the bin.
Rust -- safe, but you manage lifetimes
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { // the 'a annotations are the hard part }
Quaryn -- memory safety, zero lifetime annotations
fn longest(x: String, y: String) -> String { if x.len() > y.len() { x } else { y } }
If you know any other language, you already half-know Quaryn. Here's the same idea side by side -- first the words you write, then the commands you run.
| You want to… | Python | JavaScript | Go | Rust | Quaryn |
|---|---|---|---|---|---|
| Define a function | def f(x): |
function f(x) |
func f(x int) |
fn f(x: i32) |
fn f(x: Int) |
| A fixed value | x = 1 |
const x = 1 |
const x = 1 |
let x = 1 |
let x = 1 |
| A changeable value | x = 1 |
let x = 1 |
x := 1 |
let mut x = 1 |
let mut x = 1 |
| A data record | class P: |
class P{} |
type P struct |
struct P |
struct P |
| A set of choices | Enum |
-- |
iota |
enum E |
enum E |
| Loop over items | for x in xs: |
for(x of xs) |
for _,x := |
for x in xs |
for x in xs |
| Handle a failure | try / except |
try / catch |
if err != nil |
Result + ? |
Result + ? |
| A "maybe empty" | None |
null |
nil |
Option |
Option |
| Text with values | f"{x}" |
`${x}` |
Sprintf |
format! |
f"{x}" |
| A quick function | lambda x: |
x => ... |
func(x) |
|x| ... |
x => ... |
| A list | [1, 2] |
[1, 2] |
[]int{1,2} |
vec![1,2] |
[1, 2] |
| A key/value map | {"k": 1} |
{k: 1} |
map[...] |
HashMap |
["k": 1] |
| An empty map | {} |
{} |
make(map) |
HashMap::new() |
[:] |
| You want to… | Python | Node.js | Go | Rust | Quaryn |
|---|---|---|---|---|---|
| Run a file | python app.py |
node app.js |
go run app.go |
cargo run |
quaryn run app.qry |
| Check it without running | -- |
-- |
go vet |
cargo check |
quaryn run --check app.qry |
| Run the tests | pytest |
npm test |
go test |
cargo test |
quaryn test app.qry |
| Try code live | python |
node |
-- |
-- |
quaryn repl |
| Run at top speed | -- |
(automatic) |
(compiled) |
--release |
quaryn run app.qry |
| Run the simple way | (default) |
-- |
-- |
-- |
quaryn run --no-native app.qry |
Notice the pattern: one tool, quaryn, does everything -- run,
check, test, explore. No separate installers, formatters, or build files
to learn.
Quaryn is deliberately small -- you can hold the entire language in your head. These are essentially all of its keywords and built-in actions.
Keywords -- the grammar
fn define a function let name a value mut …and allow it to change struct a data record enum a set of choices impl attach methods to a type interface a shared capability match handle every case if else branch while for loop return hand back a value import use another file uses declare your powers
Built-in actions -- the verbs
println show a line http_get http_post call an API http_serve become an API json_decode JSON → your types spawn channel do things at once sha256 verify hashing & signatures crypto_encrypt lock data crypto_decrypt unlock data read_file write_file files now_ms sleep_ms time assert check while testing
Security and web features that are add-on libraries elsewhere are built into Quaryn itself -- encryption, signatures, JSON, and an HTTP server all ship in the box.
Quaryn was designed around one promise: fast memory, fast iteration, and APIs that just work. That points at a few sweet spots.
Take JSON in, send JSON out. A complete order service fits in one readable file -- no framework, no glue.
Drop Quaryn inside a program written in Python, Node, or anything else, and run little scripts safely -- even in a locked-down "can't touch the network" mode.
Quaryn is also planned to play a role inside PATANYX Browser, bringing selected automation features into the browser while keeping the same rule at the center: code only gets the powers it explicitly declares.
Hashing, encryption, and digital signatures are one line each, built on established cryptographic primitives -- no risky do-it-yourself crypto.
One self-contained program, no runtime to install on the other end. Write it once, hand someone the single file.
When failures must be explicit and every state must be handled, Quaryn catches entire classes of mistakes before the code runs.
All the powerful concepts -- ownership, pattern matching, no-null -- without the wall of syntax that usually guards them.
Quaryn makes its three execution strategies explicit. The exact same source can run three ways -- a simple readable mode, a portable mode, and a top-speed mode that turns hot math into real machine code -- and you pick. Here is the same work timed on all three, next to the four languages Quaryn draws from.
| The job | Quaryn native (default) |
Quaryn VM |
Quaryn interpreter |
Rust | Go | Python | JavaScript |
|---|---|---|---|---|---|---|---|
| Number crunching a tight math loop |
2 ms | 326 ms | 766 ms | 2.1 ms | 2.4 ms | 384.2 ms | 53.7 ms |
| Working through a list build it, then read it back |
7 ms | 164 ms | 359 ms | 2.4 ms | 5.5 ms | 209.2 ms | 34.4 ms |
| Chewing through JSON half a megabyte, decoded and re-encoded |
58 ms | 58 ms | 57 ms | 16 ms | 42 ms | 62 ms | 31 ms |
| Hammering a lookup table hundreds of thousands of key lookups |
68 ms | 80 ms | 139 ms | 3.3 ms | 7.0 ms | 65.0 ms | 26.9 ms |
Three engines sound like three chances to get it wrong. It's actually the opposite, and it's the reason to trust a language this young.
The three engines implement one language, not three dialects. Any program whose result is decided by the program itself -- no clock, no network, no thread timing -- must come out byte-for-byte identical on all three. That's not a promise in a README: it's checked on every single change across the whole example and test corpus, plus thousands of randomly generated programs.
The honest boundary: a program that asks the clock for the time, or talks to the network, has no fixed answer to compare -- it prints something different every run on any engine, in any language. Those are excluded from the comparison for that reason, and the generated programs are built without them.
What that means for you: the simple engine is slow but almost impossible to get wrong, so it acts as the referee for the fast one. If you ever suspect the speedy engine mangled your program, you run it the simple way and compare -- one command, no bug report, no waiting. Most languages ask you to take the fast path on faith. Quaryn hands you the receipts.