I think the YAGNI (You ain’t gonna need it) way of doing things in Odin (no package manager, etc.) keeps it simple and focused. And that’s what makes it easy to learn as well.
I am still very much a noob so I don’t have any feedback on anything specific really. I have just been very happy how easy it has to been learn (I still got ways to go but anyway!).
strings. c strings are just such a giant pain. i don’t have to write a custom string layer with macros to turn literals into structs with a char pointer and a len and so on and so forth.
declaration syntax and type inference. foo := bar is great. also it being unified across procs and vars and whatnot is amazing. not sixty trillion different ways to declare a function (cpp). ESPECIALLY declaring stuff in different scopes is the same. i can make a proc local to a scope to make sure its only callable in that scope for example. this is a candidate for my favorite
ANONYMOUS PROCS. e.g. when setting a callback or function pointer i don’t need to declare it somewhere else and name it and blah blah blah.
multiple declarations and assignment. a, b = b, a is nice
simple build model - i don’t need a PHD in meaningless bs to build an odin project, even when its big or i’m using other people’s code (legally) and etc. I also can build the compiler itself without said PHD
for a in b
sane and powerful switch statements e.g. case 123, 456: stuff.
multi pass compiler - no forward declarations, no #include tree management, etc. i do all my imports at the bottom for example and i put stuff that i’ll look at more higher up.
things that could be problems are searchable e.g. #partial or cast(type)
defer. its nice
named params, default arguments, named returns, multiple returns etc.
explicit proc overloading - so much easier to see what a function call could be
builtin math stuff types and good math libs included wooooo. myfloatarr.r
zii by default. absolutely huge
or_* operators are really n ice
ENUMERATED ARRAYS AND BITSETS - absolutely fantastic. No need to generate tables or enums where each member is a different bit.
slices are absolutely fantastic. the syntax is awesome too.
custom allocators and them in context. also temp allocator. I use my own allocators (or fixed-size structures) pretty much exclusively.
rtti is nice and type info in general
type features help string formatting be not terrible
open source, hackable compiler and included libraries.
Array programming has been the most useful feature, but my favorite is either the name : type = value syntax or using the pointy ^ to refer to pointers.
Something that stands out to to me about Odin is the strange lack of bad features…I say strange because it’s usually pretty easy to point out the pain points in other languages I’ve used.
it’s not really any single feature, but the all around design of the language.
I read this paraphrased quote somewhere about the Burroughs B5500 Computer:
“If you knew what A, and B did, and guessed what C did, you would be right.”
I feel like this describes odin well, it’s really easy to just write code, and get it right on first try.
It’s maybe a relatively small thing compared to some other answers but: array arithmetic and matrices as a type.
These two are used in almost every gamedev project I’ve done (or am doing)
It’s very hard to think of one thing that’s my favorite part of odin because my favorite thing is an abstract feeling of how well it all fits together. It’s genuinely a “replacement” for C if you want it to be, while providing significant improvements in many ways that all fit together. There are maybe things I’d change, but I’m not at all confident I could make everything fit together as well as Ginger Bill has done, and I increasingly trust his judgement on language design even where I’ve not 100% liked something at first.
Two things that stand out for me that perhaps are not syntax related are :-
A directory being a package. Being able to split up your package into multiple files for convenience but have them act as a single module is such a breath of fresh air compared with C or C++ that I’m used to
The (lack of) a build system. I use CMAKE for C++. For reasonable sane builds it’s not the nightmare some people seem to think. I don’t mind it. Then one of the reasons I stopped being so interested in ‘zig’ was it’s build system. I don’t want to write a program using a badly documented API in a language I’m still learning just to build and link a few files. The build system was one of the things that lead me away from zig. People seem to love it, I don’t get why., For odin I can just do “odin build thing” 95% of the time and it does. If I want to link with some C code, the info is in the interface files. Love it.
Memory allocation. new/delete/defer is what I want. I’m not a person who hates C++ so I do sometimes miss being able to use RAII and so on, but Odin’s approach is good too. Either works well if you know what you are doing and write in the appropriate style. I like Odin’s approach better but sometimes miss C++ too.
And allocators. I read of things from the gamedev world about arena and frame allocators. They work well there, perhaps not so well in other areas of software. In C++ using allocators even with PMR is a bit difficult and obscure. I zig you are basically forced to use allocators up front. I like the Odin approach where allocators are easily available if you want to use them but invisible when you don’t
Oh, I like the ability to do this as well (the part where it’s assigning either the date or time parts of the structure to the variable because, I assume, of the “using” in the DateTime struct)
package main
import "core:fmt"
import "core:time"
import "core:time/datetime"
main :: proc() {
today_date: datetime.Date
today_date, _ = time.time_to_datetime(time.now())
fmt.println("Today is: ", today_date)
today_time: datetime.Time
today_time, _ = time.time_to_datetime(time.now())
fmt.println("Today is: ", today_time)
}
Some might not consider it a feature but: most of my code flows, everything follows the path of least resistance. And this is an overall theme with the language, I never struggled with reading anything in core/vendor so far. It allowed me to take more control into my hands, where I’d resort to other techniques using mainstream languages due to atrocious DX.
I think your first point is shown pretty strongly about how little “talk about odin” is happening around. One of the few places where programmers are more interested in getting the computer to behave rather than figuring out fancy ways to write code
M favorite things about Odin are the readability, the incredibly logical take on multiple return values, the or_* operators, simple nil-based unions, and “^ is the pointer operator, because it’s pointy.”
Im a new programmer, but i like its extreme simplicity, like “C”. And its readability. A readable software is always less prone to error, performant, maintainable and easy to contribute. I would choose readability and simplicity anyday over some convoluted code.
Errors a a value with syntaxis sugar to avoid the GO trap. Not to have to handle all possible errors (ex: out of memory)
data and code separated properly, no OOP BS. Smart polymorphism and generics
no RAAI, no GC → defer and allocators
package = folder. Simple, efficient, avoid package cycles that is fundamentally a wrong good “feature” for the users
all the nice (and today necessary) addons in the language already here: for x in range/containers, map, matrix, tagged unions, SOA, etc…
Best interaction with C so far (Zig is impressive but too permissive by allowing native C code directly in the language → now all C complexity/problems have been catapulted in ZIG, and C complexity is composing with ZIG language complexity → explosion of edge cases / raised Github issues)
The design of the language itself. It’s simplicity is at another level. It’s so straight forward and clear that even reading the “core” library is a super smooth and straight forward experience.
Again as a newbie, the main thing for me is that we have a really flexible first-class dynamic array, and slices are just slices.
The reason I really like this separation is because (for instance) in Go, slices are slices, but they also have to double up as your first-class ordered growable, and you end up having to learn, parse and re-use a bunch of unergonomic “slice tricks”, which are prone to error. It creates conceptual confusion on top of being unsatisfying to use.
Odin, on the other hand says: Let’s give slices their original job, and I’ll also give you this really powerful growable data structure as a first-class citizen so you can get on and push, pop, insert, remove, whatever.
It’s a really big thing for me, honestly. Other than that the main thing is Odin is the living embodiment of that Einstein quote (probably supriously attributed): “Make things as simple as possible, but no simpler.” I feel like Go tried to be too simple with how slices are used and ended up making them more complicated than they needed to be.
After Odin I can’t take a language seriously if it doesn’t have implicit selector for enums.
Also the fact that you can access the members of vectors of size 1 to 4 with .xyzw and .rgba
Procedures being public by default is also great