The C3 Programming Language
AI coding and low‑level languages
- Several comments argue LLMs make “harder” but safer languages (Rust, C3, Haskell) more attractive, since strong typing and explicitness give models better context and compilers catch more bugs.
- Others note LLMs are currently better at popular languages (Python, JS), but people report good results on large Rust codebases with clear scaffolding and tests.
- A pattern emerges: LLMs work best once a codebase’s structure and style are established; greenfield work needs tighter tasking and constraints.
C3’s goals and major features
- Positioned as “evolution, not revolution” of C: keep C mental model and ABI, add modern features and safety.
- Key differences from C mentioned: modules instead of headers, semantic macros, slices, operator overloading, value methods, generics via modules, defer, compile‑time execution and reflection, contracts, fewer UB cases, safe mode runtime checks, arena-style
@poolblocks, C‑ABI compatible “Result”-likeOptional, and exception‑like “Excuses”. - Full C ABI compatibility is seen as a killer feature by some (drop‑in with existing C build systems, easy library interop); others question how important that really is.
Comparison to Zig, Odin, D, Nim, etc.
- C3 is framed as closer to C/Odin/“Better C” D than to Zig’s more radical compile‑time model.
- Differences vs Zig called out: modules instead of “file = module”, first‑class lambdas, dynamic interfaces, and operator overloading (e.g., for math types).
- Some prefer Nim‑style pervasive value semantics; others argue implicit heap copies are a non‑starter for “better C” and games/perf‑sensitive workloads.
- General view: all three (Zig, Odin, C3) are viable “better C”s with different trade‑offs; documentation maturity, syntax taste, and stability heavily influence choices.
Error handling, Optional naming, and contracts
- C3’s
type?“Optional” is semantically closer to a C‑styleResult<T,int>than toOption<T>; several commenters strongly dislike reusing the word “Optional” for aT or error-code. - Some think unifying on a single result pattern is pragmatic and matches C idioms.
- Contracts (pre/postconditions) spark debate: they can guide optimization and static analysis, but the spec allows compilers to assume they’re always true in “fast” mode, making violations unspecified.
- Critics see this as a dangerous footgun that can silently introduce miscompilations.
- Defenders say this just formalizes patterns already done with asserts and “assume” intrinsics; “safe” mode checks them at runtime.
Control flow, syntax, and small design quirks
- Switch semantics: empty case → fall‑through, non‑empty → implicit break.
- Some find this “least surprise”; others say mixing implicit behaviors is confusing and a refactoring hazard.
fnkeyword before functions is controversial: some dislike the visual noise; supporters note it simplifies parsing, avoids C’s declaration ambiguities, and enables order‑independent declarations.- No
goto: justified by availability ofdefer, labeled break/continue, andnextcasefor switch; a few low‑level programmers missgotofor certain control‑flow patterns. - Array details: multi‑dimensional fixed arrays have reversed index order between declaration and access, and slices support two syntaxes (
start..endvsstart:len), both criticized as potential footguns.
Compilers, LLVM, and performance
- C3 uses LLVM; some see this as enabling quick multi‑platform support, others argue LLVM’s complexity and slowness hold back compiler innovation.
- There’s a side debate about whether hobby languages should target LLVM, lighter backends like QBE, or custom machine code; incremental compilation vs simply making compilers radically faster is also discussed.
Adoption and use cases
- C3 is viewed as attractive where you’d otherwise pick C but want better ergonomics and tooling: embedded (ESP32 examples), games, and systems code that must interoperate with existing C.
- Some worry about low mindshare and the Lindy effect, and would still default to C for serious, long‑lived low‑level projects.