# Coming from another language

What carries over from Rust, TypeScript or Go, what is deliberately different, and what Vyrn does not have at all.

## Validation

The thing that is most likely to be new is where a rule lives. In the languages beside it a rule is code somebody has to call: a constructor, a schema object, a validating function. The type says nothing about whether it ever ran. In Vyrn the rule is part of the type, so `Age` is a number that has passed it.

The compiler proves what it can while the program compiles. So `Age(30)` costs nothing at run time, and `Age(5)` is a compile error rather than a failed check. Input from outside the program is not a constant, so it takes the total form. `Age?(n)` answers `Option<Age>`, and no path produces an unchecked `Age`.

## Ownership

Rust says this with borrows and lifetimes, TypeScript cannot say it at all, and Go says it with a pointer and a comment. Vyrn writes the intent on the parameter as a word: `read`, `modify`, `consume`.

There is no lifetime grammar to learn, because the word is the whole declaration — the compiler decides where the value is released from what the words say. [Ownership, consume, regions](https://vyrn-lang.github.io/guide/ownership.html) is the chapter that teaches it.

## Errors

There is no null and no exception. An absent value is `Option`, a failure is `Result`, and `?` hands a failure to the caller unchanged — the same three shapes Rust uses, without the conversion traits.

A `panic` is for a case that cannot happen. Nothing unwinds: there is no `catch` anywhere in the language, so a panic ends the program.

## Records and enums

A `record` is a struct with named fields and no inheritance. An `enum` is a closed choice with payloads, and `match` covers every case. The compiler counts the arms, so a new variant is a compile error at every site that reads it.

Generics are monomorphised, protocols are how a type says what it can do, and a protocol bound is checked at the call rather than at run time. Records are structural, as in TypeScript: a record with the same fields, or more, fits where a record type is wanted.

## What Vyrn does not have

**No garbage collector.** Memory is released where the ownership words say it is, and the editor's hover shows that decision per binding.

**No exceptions, no unwinding, no `async` colour.** A program is a program; the runtime that serves HTTP is a library written in the language.

**No macros.** A generator is an ordinary Vyrn function that runs while you compile and emits Vyrn — `vyrn emit-gen` prints exactly what it wrote. [gen fns and generators](https://vyrn-lang.github.io/guide/generators.html) is the chapter.

**No inheritance and no null.** Both are covered above, and neither has a workaround to learn.

## Next steps

If you write Rust: read [Ownership](https://vyrn-lang.github.io/guide/ownership.html) first — it is the chapter where this language differs from yours the most, and it is shorter than you expect.

If you write TypeScript: read [Values and types](https://vyrn-lang.github.io/guide/values.html) and then [Errors](https://vyrn-lang.github.io/guide/errors.html). Numbers state their width here, and validation is a type rather than a library.

If you write Go: read [Records, enums, match](https://vyrn-lang.github.io/guide/records.html) — the closed enum and exhaustive `match` are what replace the interface-and-type-switch pattern.

The [benchmarks](https://vyrn-lang.github.io/benchmarks.html) answer the other question a reader arrives with, and every reading there is published.

---

From https://vyrn-lang.github.io/guide/coming-from.html — generated by `site/export.vyrn` from the Vyrn repository.
