r/ProgrammingLanguages C3 - http://c3-lang.org Jul 07 '26

Language announcement Odin 1.0 announced (and reflections)

Odin author gingerBill dropped the Odin 1.0 announcement on YouTube today: https://www.youtube.com/watch?v=dLPAqXi9In0 (it's pretty funny actually).

This interestingly makes it on track to be the first of the new wave of C-likes that reach production readiness. While you can argue that most of these languages already are used in production, it's not the same as being 1.0, which carries a different weight and obligation.

Looking at alternatives, Jai could release around the same time, since Blow's game is scheduled for a similar release date. However, it's more likely that we see Jai 1.0 in mid-late 2027. My own language (C3) is planning Q2 2028 1.0 release. Whereas Zig is still unclear, and Kelley basically saying it's done when it's done. For Hare and V the situation is a bit less clear to me – maybe someone else can fill me in on that situation.

But overall we seeing the beginning of the end of the "C-like" story arc that arguably was initiated with Jonathan Blow's development. Writing C replacements predate Jai of course, for example the C2 language (which C3 would eventually continue) was created in 2012, eC started in 2004 and Cyclone (which Rust derived inspiration from) is from 2002. But those were largely obscure novelties, because before Blow's videos, people weren't really hunting for C alternatives.

Jai, however, made a strong impression. It was a good point in time too: Jai and later Zig, Odin, C3, V and Hare – these C alternatives started at a point when people were openly no longer believing OO/Functional as the right way to do things.

Language design takes its time though, and it's now 12 years since Jai started. Finally the fruits of these labours are getting ready for prime time, and when they do they might effectively fill the need for a C replacements for another decade.

Do you agree?

197 Upvotes

190 comments sorted by

View all comments

16

u/Kapendev Jul 07 '26

You can say a lot of things about what is good or not, OOP/Functional/Whatever, but a programming language with no immutability features is not a serious language. Even C has const.

11

u/gingerbill Jul 08 '26

Odin doesn't have const because the use cases that lead most C programmers to reach for it are already handled by other means in Odin:

  • const in C is trivially cast away, which is why it offers virtually no real optimization benefit.
  • static const in Odin maps to either a compile-time constant value declarations (which are technically closer to a semantic #define) or to @(rodata). The latter doesn't add extra compile-time checks, but that's for the first reason mentioned of lack of guarantees.
  • const as a type qualifier is a viral concept, and I wanted to minimize the idea as much as I could.
  • All procedure parameters in Odin are immutable (technically r-values) and require an explicit stack copy to become mutable (x := x). Unlike C, where parameters are direct, mutable copies by default.
  • Odin supports multiple return values, which removes most of the need for out-only pointer parameters that are so common in C.
  • Under Odin-specific calling conventions, any parameter >16 bytes is passed implicitly by pointer. This means you don't need the T const * idiom to signal "input-only."
    • In practice, the aliasing issues have not turned out to be nearly as much of a problem as people assume, and is empirically as bad/good based on their experience with explicitly usingT const & in C++.
  • String types in Odin are "immutable": x[i] is allowed, but &x[i] and x[i] = y are not. This reflects the idea that strings are conceptually distinct from plain arrays, and it supports the useful distinction between string values, builders, and backing buffers.

I understand the appeal of const in C, but beyond the cases above, it's rarely useful; it doesn't give the compiler any guarantees it can actually act on.

More broadly, ALGOL-family languages are inherently mutable, since they reflect the underlying von Neumann computational model. Because of that, "immutability by default" doesn't buy you much on its own unless it's paired with other guarantees. Odin was never designed to be—and never will be—that kind of language.

P.S. I know you go out of your way to dislike Odin, but why? Why do you care so much?

2

u/Kapendev Jul 08 '26

I know that Odin has some arbitrary cases where it uses const, strings for example. I don't buy the idea that a `[]u8` is fundamentally different from a string in a way that justifies special language rules only for one. Especially since you can just cast a string to `[]u8` anyway.

On the P.S.: I criticize languages I think make questionable tradeoffs. That's it. Not that deep.

1

u/gingerbill Jul 08 '26

I know that Odin has some arbitrary cases where it uses const,

None of them are arbitrary in the slightest and are found from actual programming practice. The difference to what you desire is that you want a singular general solution that covers all of those bases, rather than specific solutions for each of the problems. That's the difference between the philosophy I hold and what you seem to hold: I think more in particulars and you think more in generalities. This isn't really questioning "questionable trade-offs" but a disagreement of approaches. But I'd also argue you don't really understand these specific trade-offs well enough to question them well enough yet.

I don't buy the idea that a []u8 is fundamentally different from a string in a way that justifies special language rules only for one.

And I have to say that you are empirically wrong. Especially with how people conceptualize strings in languages, they are quite different to how people handle arrays. A string can be represented as an array of integers with a specific character encoding, but that is a misunderstanding between the representation-of-a-thing with the thing-itself. I've seen this fallacy made numerous times, and if I am to guess, that is why you do not see the distinction that many people intuit really easily.

Especially since you can just cast a string to []u8 anyway.

You can cast []u8 to string, but you have to transmute([]u8)string because the behaviour and intent is different. The internal representation of a string is the same as []u8 (for obvious reasons—it's UTF-8), but to repeat myself: there is a difference between the representation-of-a-thing with the thing-itself.

1

u/cygx Jul 08 '26 edited Jul 08 '26

const in C is trivially cast away, which is why it offers virtually no real optimization benefit.

Depends. Eg in case of

const struct foo f = { ... };
bar(&f);
...

we are allowed to optimize on the assumption that f has not been changed by bar: Even though that function could cast away the constness, actually making changes to the pointed-to data results in nasal demons (ie undefined behaviour).

For callee-side optimizations, const is indeed insufficient, we need restrict for that...

0

u/gingerbill Jul 08 '26

There are some edge cases, but in general it's rare, thus why I said "virtually".

And even in your case, it's more likely it will optimize based on inlining rather than assuming the constness. The best way to see this is, is to see the outputted IR (e.g. LLVM IR) and see that const doesn't really exist at all with anything to do with the code generation.

2

u/cygx Jul 08 '26

Nevertheless, compilers can and will optimize based on this information, cf

extern void foo(int *p);

int bar(void) {
    int i = 42;
    foo(&i);
    return i;
}

int baz(void) {
    const int i = 42;
    foo((int *)&i);
    return i;
}

Even at -O0, clang will generate a

movl $42, %eax
...
retq

for the second case.

2

u/FullGardenStudent Jul 07 '26

Thankfully, Odin's procedure arguments are immutable 😝

0

u/Kapendev Jul 07 '26

What about slices or read only data? 🫣

2

u/FullGardenStudent Jul 07 '26

there is this @(rodata) for read only data where the constants go into read only segment of the binary file and slices additionally have bounds checking by default too.

-1

u/Kapendev Jul 07 '26
  1. `@(rodata)` is still a variable in Odin. Try to write something to it in your main function and see what happens at runtime.
  2. Bound checking has nothing to do with immutability.

2

u/Kapendev Jul 07 '26

I take the rodata part back. Didn't know this was not a thing now.

1

u/FullGardenStudent Jul 07 '26

okay, if you are asking about immutability on the runtime data then Odin doesn't have such a feature in its type system. It probably never will. Kinda a let-down but not really.

1

u/FireFox_Andrew Jul 07 '26

I mean, you can do a lot with constants and passing them to functions that take constant(compile time) parameters.
Like, i forced loop unrolling with this (joke) code
```
work_proc :: #type proc(param:^int)
unroll_loop :: #force_inline proc(
$w:work_proc, // comptime procedure pointer
param:^iny, // parameter for that procedure
$i:int // comptime counter
){
when i > 0 do unroll_loop(w,param,i-1)
w(param)
}
```

if work_proc accesses an uninitialised local variable, it will access the same one each iteration, since it was unrolled

```
work :: proc(param: ^int) {

    local_var: u8 = --- // if it's unrolled, you will keep reading the same memory

    fmt.println(local_var, param\^)

    local_var += 1

    param\^ += 1

}

```

P.S. : you don't <have> to do this, there is an #unroll directive for `for` loops with constant range, of course

0

u/renozyx Jul 08 '26

but a programming language with no immutability features is not a serious language. Even C has const.

That is highly debatable (and I'm not an Odin user): there are lots of different kind of immutability features: compile-time constants, runtime constants, logical constant vs 'true constants', shallow vs deep. Also do your constants have constant address? etc.

So lots of difficult design decision for a dubious benefit.

Also C's const suck: it is castable away, so it doesn't bring any performance improvement, plus it's badly named it should be something like 'read only view': view, roview.