Coming From Another Language: C++
● Beginner6 minBefore this: Coming From Another Language
From C++: native speed with no undefined behaviour, no manual memory, errors in the signature, and Drop where you would use RAII.
Here is one small program twice: in C++ as you would write it, then in Kavach. Orders with a quantity and a price, a total that refuses an order with no quantity, and discount codes that may be missing. Both print the same three lines.
#include <iostream>
#include <map>
#include <numeric>
#include <stdexcept>
#include <string>
#include <vector>
struct Order {
std::string item;
long qty;
long cents;
long cost() const { return qty * cents; }
};
struct BadQty : std::runtime_error {
std::string item;
explicit BadQty(const std::string& i) : std::runtime_error("no quantity for " + i), item(i) {}
};
long total(const std::vector<Order>& orders) {
for (const auto& o : orders) {
if (o.qty <= 0) throw BadQty(o.item);
}
return std::accumulate(orders.begin(), orders.end(), 0L,
[](long sum, const Order& o) { return sum + o.cost(); });
}
int main() {
const std::map<std::string, long> codes{{"SPRING", 10}, {"VIP", 25}};
const std::vector<Order> orders{{"pen", 3, 150}, {"cup", 1, 900}};
long sum;
try {
sum = total(orders);
} catch (const BadQty&) {
sum = 0;
}
auto found = codes.find("SPRING");
long off = found != codes.end() ? found->second : 0;
std::cout << "total " << sum << ", with " << off << "% off " << sum * (100 - off) / 100 << "\n";
auto winter = codes.find("WINTER");
std::cout << "WINTER gives " << (winter != codes.end() ? winter->second : 0) << "%\n";
const std::vector<Order> broken{{"kite", 0, 500}};
try {
long t = total(broken);
std::cout << "total " << t << "\n";
} catch (const BadQty& e) {
std::cout << "refused: no quantity for " << e.item << "\n";
}
}type Order {
item: String
qty: Int
cents: Int
fn cost(self) -> Int {
self.qty * self.cents
}
}
type OrderError = BadQty(item: String)
fn total(orders: [Order]) -> Int ! OrderError {
for o in orders {
if o.qty <= 0 {
fail OrderError.BadQty(item: o.item)
}
}
orders.sum(o => o.cost())
}
fn main() {
const codes = ["SPRING": 10, "VIP": 25]
const orders = [Order(item: "pen", qty: 3, cents: 150), Order(item: "cup", qty: 1, cents: 900)]
const sum = total(orders) catch _ => 0
const off = codes["SPRING"] ?? 0
print("total {sum}, with {off}% off {sum * (100 - off) / 100}")
print("WINTER gives {codes["WINTER"] ?? 0}%")
const broken = [Order(item: "kite", qty: 0, cents: 500)]
match total(broken) {
ok(t) => print("total {t}"),
err(OrderError.BadQty(item)) => print("refused: no quantity for {item}"),
}
}The program ran and printed:
kavach run orders.kav
total 1350, with 10% off 1215WINTER gives 0%refused: no quantity for kite
What changes
| In C++ | In Kavach | Learn it |
|---|---|---|
a struct or class with methods | type Order { … }, its methods inside it | Records |
inheritance and virtual | interfaces: a type says which ones it implements | Interfaces |
| exceptions, unseen in the signature | ! OrderError in the signature, and try or catch at each call | Errors |
nullptr, or find() against end() | T?, and ?? 0 for when it's missing | Optionals |
new, delete and smart pointers | no allocating or freeing: a value is freed after its last use | Automatic Memory |
| RAII destructors | Drop: drop runs when the block holding the value ends | Freed immediately |
| signed overflow is undefined behaviour | overflow stops the program with a panic | Int |
v[5] past the end is undefined behaviour | xs[5] panics; xs.get(5) gives none | Reading by index |
| templates | generics: fn first<T>(items: [T]) -> T? | Generics |
std::thread and std::mutex | spawn, and Shared<T> for what tasks change together | Shared State |
| headers and a build system | modules with use, one kavach.toml, kavach build | Modules |
| raw pointers anywhere | raw memory only inside unsafe { … } | Unsafe |
The C++ version shows a trap of its own: std::cout << "total " << total(broken) prints total before total throws, so it is split into two statements.
Habits from other languages get a clear error that says what to write instead: see Habits from other languages.