How did Odin make you a better C programmer?

Original Tweet: x.com

I constantly see people say that learning Odin actually made them a better C programmer.

What things about Odin made you better at programming in C? I am genuinely curious.

3 Likes

For me it was initially a culture shock of “no methods, only structs and free-standing functions” that led to realization that methods are essentially a syntactic sugar.

What is the difference between these 2?

mything.do_foo(x);

vs

thing_do_foo(&mything, x);

As soon as it clicked that methods are just a syntax sugar that also applies restrictions on who and where can add them reading C code became much easier - I am no longer looking at C as “this old weird way of doing things” and instead I see it as “this is the right way of doing it”.

TLDR: separating data and functions leads to cleaner program design for me.
So thanks @gingerBill , you helped me to debug my brain :smiley:

7 Likes

I have to say that it was the openness of the language and core libraries combined. Odin was like an invitation to learn more that I just hadn’t been able to find in C because of some fog to me that was present in both C and C++. If I had come about in a different tradition (non-OOP and such) or had better opportunities, I think I’d be completely fine in C without Odin. C is definitely capable, if broken.

Culture shock is a good way to put it. I have learned almost everything I know in programming through self-study, and it’s almost impossible to judge the merit of one learning material to another when you know nothing about the subject (no matter what we’re talking about: programming languages, sculpting, and so on), so having a completely different environment like that forced me to take a second look at much of my thinking. I’ve been able to dispel a lot of unproductive ways of doing things, and the simplicity of Odin helps with that.

I’ve always been fond of C for its weathered age and relative simplicity to C++, but its lack of parametric polymorphism made it tough to work with, because I often used standard containers available to whichever language. So, in essence, I didn’t know how to build my own for a long time, and I was never fond of using or writing preprocessor macros. It felt like a terrible code smell to me to have to re-write array APIs for every struct type I wanted to be able to gather. I think today I could handle it well, in a couple different ways.

In short, I had the potential, but it just needed the right moment to bloom.


Come to think of it, I had a similar experience with Lua, many, many years ago, but it wasn’t anywhere nearly as deep as the one I had when I tried Odin. For one, Lua isn’t even remotely a low-level programming language, but it did give me a way to reorient myself and get a new perspective on things for a while.

Lua provides virtually nothing outside of a few standard library mechanisms. It’s not low-level (it has a GC, no syscalls, no builtin C FFI), but it is small. For the longest time, there was no package manager either (and I think they still don’t have an official one), so you had to build your own tools. I think that’s one of the great unspoken boons to not having a package manager: for once, you have to consider how you’re going to build something without resorting to the instant gratification of npm install left-pad.

That right there can be an amazing learning opportunity.

6 Likes

Here’s my list:

  • ZII
  • assertf
  • slices
  • Both because of this and Odin’s simple & open array design, I’m using many more static arrays
  • occasionally, I consider unicode
2 Likes

Odin makes working with pointers easy without the need to remember to flip flop between -> and . when using pointer structs. The pointer dereference (^) is also nice and non ambiguous. Overall for me odin represents a middle ground between c its self and a language like rust as I can perform type based switch statements and still get the freedom of not being told what todo by the compiler and manage memory at the same time.

Like Feoramund, I like C, but I embraced the preprocessor in all its pasta. Global namespace be damned! Am I better C programmer if I squint my eyes and pretend it’s Odin?

Dynamic(long) list = dynamic_make(long);
for (int i = 0; i < 1000000; i += 1) {
    dynamic_append_elem(&list, rand());
}
sort(list);
long prev = 0;
for (long* it = begin(list); it != end(list); it += 1) {
    assumef(*it >= prev, "wtf sort: %ld > %ld", prev, *it);
    prev = *it;
}
Slice(long) upper_half = slice(list, list.len / 2);
sort_desc(upper_half);

Finding simple bugs with some print outs and bounds checking is so much better than working backward from a crash in a debugger.

5 Likes

I started using the following in C, after some time with Odin

  • Fixed Width Integer Types
  • Arenas over malloc
  • ZII
  • Slices/Spans instead of pointers
  • Consistent Error Propagation
  • A context struct that’s always available (using Thread Local Storage instead).
2 Likes