What Kavach Does for You
Also known as: features why kavach benefits smart defaults safety speed
● Beginner8 min
The things Kavach does without being asked: fewer mistakes, exact numbers, clear messages, speed and safety. Each one links to its proof.
Much of what makes Kavach pleasant never shows in your code: the compiler and the runtime do it for you. Here is all of it in one place. Each item also appears on the page that teaches it.
Fewer mistakes
Comparisons chain, as in mathematics
0 <= i < items.len()means both tests, and the middle is worked out once. Any mix chains:a == b != cisa == b and b != c. Noandto forget.== compares contents
Two lists are equal when their items are; two maps when their entries are, in any order. A copy that was never changed is equal in one step, without looking inside.
No truthiness
A condition must be a
Bool.if countis an error, so0,""andnonecan never be taken for false by accident.match covers every case
Add a new variant to a union and the compiler lists every
matchthat must now handle it. Nothing is forgotten silently.Maps and sets keep their order
Looping over a map visits entries in the order they were added, so a program prints the same thing every run, and tests stay repeatable.
Ranges say which end they mean
0..10stops before 10;0..=10includes it. Non - 1orn + 1to get wrong.const unless it must change
constvalues never change, and changing one is a compile error that says to uselet. You see at a glance what can move.Taking values apart is typed
const [first, second] = scoresworks on any list: a missing item becomesnone, and its type says so.Comments nest
/* … */may hold other block comments, so code that has comments can be put aside whole.Every index is checked
Reading item 5 of a two-item list stops the program with the index and the list's length. It never reads memory that isn't the list's.
Asking for a number asks until it gets one
term.prompt_intanswers "thirty" withPlease type a whole number.and asks again, so your code only ever sees a number.A forgotten result is caught
Calling a function and ignoring what it gives back is an error, the classic bug of making an updated copy and never using it.
const _ =says "on purpose".
Numbers and types
Overflow is caught, never wrapped
An integer that goes past its type's limit stops the program with a clear message, instead of quietly turning into a wrong number. When the compiler knows the values, even through a loop over known numbers, it is a compile error.
Constants are exact
0.1 + 0.2 == 0.3istruewhen both are constants: the compiler works constants out exactly, then rounds once.A number takes its type from where it goes
const price: Decimal = 499.99is an exact decimal, not a rounded float. Without a type, whole numbers areInt.Decimal never runs out of digits
A
Decimalkeeps as many digits as it needs, so money adds up to the paisa however large it gets.Big numbers just work
A constant too big for
Int, like2 ** 100, becomes aBigIntwith the exact value. No overflow, no library.Text to number can fail, and says so
Int("23sd")is an error you must handle, never a silent0or a guess.Values print the way you write them
7.0prints7.0, aDecimalkeeps its scale, text inside a list is quoted. Output is never ambiguous.A number that can't fit is caught while compiling
const small: UInt8 = 300is refused before the program runs, and the message names the type that fits:UInt16.
Clear messages
Typos get a suggestion
Using an unknown name is an error that suggests the name you probably meant:
did you mean total?Warnings on comparisons that rarely mean what they say
==between computed floats, andx % 2 == 1(which misses negative odd numbers), get a warning with the fix.debug() shows where, and never ships
debug(x)prints the value with its file and line. Release builds leave it out, argument and all.One naming style, fixed by the formatter
kavach fmtrenames a badly styled name and every use of it, so every codebase reads the same.Unused names are flagged
A variable nobody reads gets a warning; start its name with
_to say it is on purpose.
Fast without effort
A value nobody reads is never computed
Native code skips work whose result is unused and changes nothing you could see.
Big loops use every core
A loop over a big list is split across all cores when the result is exactly the one-core result, overflow checks included.
Chains become one loop
xs.map(f).filter(g).sum()runs as a single loop: no list is built between the steps.Small numbers are packed
A list of bytes uses one byte per item, and lists of 16- and 32-bit numbers are packed too.
Small records live in registers
A record nobody else holds needn't be built in memory at all: its fields can stay in CPU registers.
Adding recursion becomes a loop
A function that calls itself to add up a result runs as a loop, as fast as one. Nothing you can see changes: a recursion too deep for the stack still stops with the same message.
A stored callback is called directly
A function kept in a record and called later is inlined when the compiler can see which one it is.
Random reads are fetched ahead
In a loop reading a big list or map at computed places, the next reads are requested from memory early.
The GPU only when it wins
A
mapgoes to the GPU only when the list is long and the work per item big enough; otherwise the CPU does it.A waiting task costs nothing
A task waiting for the network sleeps on the operating system's event queue, and only the thread that has work wakes up.
You pay only for what you use
An executable contains only the modules, functions and runtime parts the program really uses.
Memory is freed at once
No garbage collector and no pauses: a value is freed the moment nothing uses it, at a point you can predict.
Safe by default
There is no null
A value that may be missing says so in its type,
User?, and the compiler makes you handle the missing case. A null pointer error can't happen.Copies are safe, and cheap
Assigning a list gives an independent value, so changing one never changes another. It is only really copied if one of them changes.
Failure is part of the type
A function that can fail says so in its signature, and the caller must deal with it. No exceptions flying past.
Tests write themselves
kavach testtests a function from its types and contracts alone; a failure comes with the seed to replay it.Code can only touch what it declares
A function that reads files or the network says so with
uses; the compiler and the runtime hold it to that.Look-alike names are flagged
A name mixing letters from two scripts (a Latin
aand a Cyrillicа) gets a warning, so hidden look-alikes can't sneak in.Maps can't be attacked through their keys
Map hashing is seeded fresh for every run, so nobody can send keys built to make your maps slow.
No data races
Tasks can't change the same value at the same time: the compiler refuses code that could.
Tasks take turns in a fixed order
The order in which tasks take turns is defined, so a concurrent program prints the same thing on every run, and a bug shows up every time.
Agents survive a crash
A durable agent writes a journal and, after a crash, replays it to carry on where it stopped, without doing anything twice.
Agent rules the model can't talk its way past
What an agent may touch is checked when compiling, and its limits and approvals on every call, outside anything the AI model can influence.
AI answers are typed, not text
ask<T>checks the model's answer against the typeTand asks again when it doesn't fit, so code never parses loose text.Every agent call is audited
Each capability call an agent makes is written down with its verdict and result, refused ones too, without a line of logging code.
Secrets stay secret
A secret prints as
<secret>and can't reach logs or messages unless you reveal it on purpose.