Coming From Another Language: Rust
● Beginner6 minBefore this: Coming From Another Language
From Rust: Result and Option are written ! E and T?, there is no borrowing to plan, and tasks need no async runtime.
Here is one small program twice: in Rust 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.
use std::collections::HashMap;
struct Order {
item: String,
qty: i64,
cents: i64,
}
impl Order {
fn cost(&self) -> i64 {
self.qty * self.cents
}
}
enum OrderError {
BadQty { item: String },
}
fn total(orders: &[Order]) -> Result<i64, OrderError> {
for o in orders {
if o.qty <= 0 {
return Err(OrderError::BadQty { item: o.item.clone() });
}
}
Ok(orders.iter().map(|o| o.cost()).sum())
}
fn main() {
let codes = HashMap::from([("SPRING", 10), ("VIP", 25)]);
let orders = vec![
Order { item: "pen".to_string(), qty: 3, cents: 150 },
Order { item: "cup".to_string(), qty: 1, cents: 900 },
];
let sum = total(&orders).unwrap_or(0);
let off = *codes.get("SPRING").unwrap_or(&0);
println!("total {sum}, with {off}% off {}", sum * (100 - off) / 100);
println!("WINTER gives {}%", codes.get("WINTER").unwrap_or(&0));
let broken = vec![Order { item: "kite".to_string(), qty: 0, cents: 500 }];
match total(&broken) {
Ok(t) => println!("total {t}"),
Err(OrderError::BadQty { item }) => println!("refused: no quantity for {item}"),
}
}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 Rust | In Kavach | Learn it |
|---|---|---|
let mut count = 0 | let count = 0: a let can already change, and const can't | let |
struct and impl | type Order { … } with its methods inside, or in an extend | Records |
| traits | interfaces | Interfaces |
Result<i64, OrderError> | -> Int ! OrderError | Errors |
? | try before the call | try |
Option<T> and unwrap_or(0) | T? and ?? 0 | Optionals |
&, &mut, lifetimes and .clone() | none of them: values are copied, and inout marks a parameter a function changes | Values, Not References |
impl Drop | type Guard: Drop | Freed immediately |
HashMap::from([("SPRING", 10)]) | ["SPRING": 10] | Making a map |
iter().map(…).sum() | orders.sum(o => o.cost()) | map, filter, sum |
async and a runtime such as Tokio | spawn, with no async | Tasks |
| Cargo and crates | packages in kavach.toml, each granted only the capabilities its can lists | Packages |
unsafe | unsafe { … } too, and kavach audit lists every use | Unsafe |
Habits from other languages get a clear error that says what to write instead: see Habits from other languages.