The Spirit of the Language

Alright, let's talk about the vibe of this language. Every language has a personality, a philosophy, a way of looking at the world. We've worked hard to preserve and respect that core spirit. Here's what makes this language tick.

Core Tenets

These are the foundational values that drive everything:

Trust the programmer

Look, we're assuming you know what you're doing. This language is built for competent folks who understand their craft. We're not gonna baby you or add a bunch of guardrails to protect you from yourself. That's just not our style.

You're smart. You've got this. We respect your expertise and judgment.

Don't prevent the programmer from doing what needs to be done

Sometimes you need to get into the nitty-gritty. Low-level stuff. Hardware-specific operations. Whatever it takes to get the job done.

The language isn't gonna stand in your way. If you need to do something, we're gonna make it possible. Period.

Keep the language small and simple

Smaller is better. Simpler is better. A lean language is easier to learn, easier to implement, and easier to reason about.

We'd rather have features that compose nicely together than a bazillion specialized solutions for every edge case. Simplicity in the language means clarity in your code.

Provide only one way to do an operation

Having seventeen different ways to do the same thing? That's just confusing, dude. Cognitive overhead for no good reason.

We aim for one clear, obvious way to do each thing. Makes code more consistent, easier to read, easier to understand. Everyone's on the same page.

Make it fast, even if it is not guaranteed to be portable

Performance matters. Like, really matters.

We want implementations to generate fast code, even if that means some constructs might behave differently on different hardware. If you need maximum performance, you should be able to get it. Speed first, ask questions later.

What We Won't Do

Sometimes it's easier to understand a philosophy by looking at what it rejects. Here's what you won't find in this language, and why:

We're not adding automatic garbage collection. GC is convenient, sure, but it hides costs. You don't know when collections will happen, how long they'll take, or how much memory overhead you're paying. That violates "no hidden costs" and "you're in control." If you want memory management, you can build it yourself or use a library. But the language isn't gonna force it on everyone.

We're not preventing pointer arithmetic. Yeah, it can be dangerous. Yeah, it can lead to bugs. But sometimes you need it for high-performance code, interfacing with hardware, or implementing low-level data structures. We trust you to use it responsibly. If you don't need it, don't use it. But it's there when you do.

We're not adding extensive runtime safety checks by default. Bounds checking, null pointer checks, overflow detection — these are all great for debugging and they can be enabled. But making them mandatory in production code violates "make it fast" and "trust the programmer." You should be able to choose safety or speed based on your needs.

We're not restricting "unsafe" operations. There's no special "unsafe" keyword or block that you need to use for low-level operations. Everything is available all the time. Yes, this means you can shoot yourself in the foot. But you're a competent programmer — you know where you're aiming.

We're not hiding what the machine actually does. Some languages abstract away the hardware so completely that you have no idea whether an operation is cheap or expensive. That's not our style. Language constructs map clearly to machine operations, so you can reason about performance without reading assembly.

What This Means in Practice

These principles have some real consequences for how the language works:

Direct mapping to hardware. Language constructs should map closely to what the machine actually does. This makes performance predictable and lets you reason about efficiency without guessing.

For example, when you write a + b, that's literally one ADD instruction (or a few instructions for complex types). When you declare an array int[100], that's 100 contiguous integers in memory, exactly like you'd get in assembly. A pointer is a memory address — not a handle, not a reference with hidden metadata, just an address. This transparency means you can predict performance characteristics without running a profiler.

No hidden costs. We're not gonna hide expensive operations behind nice-looking syntax. What you write should clearly reflect what the computer will actually do. No surprises.

If something is expensive, the syntax should make it obvious. Memory allocation? You call alloc() explicitly. Copying a large struct? You write out the assignment. Deep iteration? You write the loop. We won't do expensive things silently behind your back. This principle is why operator overloading (if we have it) is carefully controlled — you shouldn't be able to hide a database query behind a + b.

You're in control. The language gives you mechanisms; you decide the policy. How you use the features is up to you, not dictated by the language.

Want manual memory management? Go for it. Want to build a reference-counted system? Do it. Want to use arena allocation? Your call. Want to never free anything because you're writing a short-lived tool? That's valid too. The language provides the primitives; you decide the strategy. We're not gonna mandate one true way of doing things.

Flexibility over safety. When there's a trade-off between flexibility and automatic safety checks, we tend to lean toward flexibility. We trust you to use the power responsibly.

This doesn't mean we're cavalier about bugs. Safety features are available — compile-time checks, optional runtime guards, static analysis hooks. But they're tools you can choose to use, not restrictions forced on you. If you're writing a device driver that needs to poke at raw memory addresses, the language isn't gonna stop you. If you're writing an application where safety is paramount, you can enable every check available. Your code, your choice.

How This Evolves

Real talk: these principles have been with us from the beginning, but we've learned that sometimes you gotta balance them against other concerns. Security. Safety. Different programming domains with different needs.

The core spirit is still here, still strong. But it's tempered by real-world experience and what programmers actually need to build great stuff. We're not dogmatic — we're practical.

Specific Examples of Evolution

Security concerns: Early on, we might have said "integer overflow wraps around, deal with it." But after seeing countless security vulnerabilities from unchecked arithmetic, we added optional overflow checking and made it easy to use checked arithmetic when you need it. We didn't mandate it (that would violate "trust the programmer"), but we made the safe path readily available.

Initialization: Originally, variables could be uninitialized, trusting programmers to initialize before use. But uninitialized reads caused so many bugs that we started requiring initialization or explicit marking as uninitialized. This technically reduces flexibility, but the bugs prevented far outweigh the minor inconvenience. It's still explicit — you write let x: uninitialized int if you really want that — but the default is safer.

Type inference: We've added type inference to reduce boilerplate without hiding what types actually are. Early systems programming languages made you write types everywhere. Modern languages sometimes infer so much that you have no idea what you're working with. We found a middle ground: infer types locally when it's obvious, but require annotations for function signatures and public interfaces. This maintains transparency while reducing busywork.

Borrow checking (maybe): If we adopt Rust-style borrow checking, it'll be because it prevents genuine bugs (use-after-free, data races) at compile time with minimal runtime cost. That aligns with our spirit even though it adds complexity. The key is that the checks happen at compile time (no hidden costs) and you can explicitly opt out for the rare cases where you know better (trust the programmer).

The Balance Point

The evolution isn't random. We adopt new ideas when they:

  1. Solve real problems that programmers actually face (not theoretical issues)
  2. Align with the core spirit even if they add complexity
  3. Provide clear wins that justify any added complexity or reduced flexibility
  4. Can be explained simply so they don't make the language harder to learn

We're conservative about change, but not ossified. The language serves programmers, and programmers' needs evolve. We evolve with them, but we keep our roots.

How This Compares to Other Languages

Everyone's got their own philosophy. Here's how ours differs:

Versus high-level managed languages (Java, C#, Go): They prioritize safety and convenience over control and performance. Garbage collection is mandatory, abstraction is heavy, and you can't directly access hardware. Great for many applications! But when you need that last bit of performance or direct hardware control, you're out of luck. We give you the low-level control while providing modern safety features you can opt into.

Versus C: We share the spirit of simplicity and hardware proximity, but we've learned from 50 years of C programming. We add modern features like better type safety, generics, and optional safety checks. We keep the power and transparency but reduce the footguns where we can without sacrificing control.

Versus C++: C++ tried to be everything to everyone and ended up massively complex. Multiple paradigms, template metaprogramming, implicit conversions everywhere. We respect C++'s power and backward compatibility goals, but we're okay being simpler and more focused. We'd rather be great at systems programming than mediocre at everything.

Versus Rust: Rust is amazing and we learn a lot from it. Borrow checking is brilliant. But Rust can be complex, and it makes some tradeoffs that favor safety over simplicity. We might adopt borrow checking but in a simpler form. We're willing to give programmers more rope while providing good safety tools. Different tradeoffs for different philosophies.

Versus Python/JavaScript/Ruby: These languages optimize for developer productivity and rapid development. They hide the machine completely, use garbage collection, and sacrifice performance for convenience. That's a valid choice! But it's not our choice. We're building a language for people who care about what the machine does and want direct control over it.

The point isn't that we're better or worse — we're making different tradeoffs for a different audience. If you want a language that trusts you, stays close to the hardware, and gives you control while providing modern safety tools, this is your language.

Copyright (c) 2025 Ocean Softworks, Sharkk