Skip to main content
Exploring a New Language That Feels Strict but Right
  1. Blog Posts/

Exploring a New Language That Feels Strict but Right

3 min read·
system rust memory

Published on: 2020-01-24

I recently started exploring a new programming language — one that doesn’t let you get away with much, and that might be exactly what I needed.

The language is fast, strongly typed, and designed for safety. You can’t ignore warnings, forget error handling, or accidentally misuse memory. At first, it felt like a fight. But then… something clicked.

🧪 First Encounter: The Compiler is Brutal, But Honest

I began with the classic thing — a simple command-line tool. Nothing fancy. Just parse some input, print something out.

fn main() {
    let name = "World";
    println!("Hello, {}!", name);
}

Seems familiar enough, right? Until you start trying to read from a file, handle errors, and reuse values. That’s where the language starts throwing lifetimes, borrowing, and ownership at you — and it doesn’t sugarcoat anything.

But here’s the thing: when it compiles, it works. It feels reliable.

🧯 Error Handling That Forces You to Think

One of the most surprising differences is how error handling is baked into every action. You don’t just read a file and assume it worked — you’re made to handle the case where it didn’t.

use std::fs::File;
use std::io::{self, Read};

fn read_file(path: &str) -> Result<String, io::Error> {
    let mut file = File::open(path)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    Ok(contents)
}

You can’t escape error handling here — and honestly, that’s refreshing. It makes you face the real-world messiness from the start, not just when something breaks in production.

🧠 Thinking About Memory… Without Managing Memory

The language uses a system of ownership and borrowing that took me a few tries to fully grasp. At first it feels like you’re being punished for no reason — “why can’t I use this variable again?” — but over time you realize what it’s preventing.

Data races, dangling pointers, untracked mutations… all blocked at compile time.

fn print_length(text: &String) {
    println!("Length: {}", text.len());
}

fn main() {
    let s = String::from("hello");
    print_length(&s); // pass a reference, keep ownership
    println!("Still accessible: {}", s);
}

This forces a different way of thinking. You stop guessing what’s happening with your data. You know.

🛠️ Tooling That Doesn’t Feel Like an Afterthought

Everything just works out of the box. Build system, package manager, testing, formatting, linting — it’s all integrated. You write code, run a single command, and the ecosystem takes care of the rest.

When I made a small change, formatted the file, ran tests, and built the app — all from the same CLI — I realized how rare that is.

🧪 What I’ve Built So Far

  • A file parser that watches a directory and processes new entries in real time
  • A basic API server using a minimalist framework with async support
  • A tool to benchmark code execution time across functions

Each project forced me to learn something new — and every time I hit a wall, it was because I was doing something unsafe or ambiguous. Fixing it always made the code better.

🧾 TL;DR

This language isn’t for copy-paste coders. It rewards understanding, not shortcuts. It’s strict, yes — but in a way that helps you grow as a developer.

I’m still early in the journey, but every time I go back to another language, I miss the clarity and honesty this one demands.

If you enjoy writing code that won’t let you get away with bad habits, give it a shot. You’ll know pretty quickly if it’s for you.