For me, I don't really look at Odin as a successor/fixer of C. There are other languages that can make a better case for that[1][2]. Instead, I look at it more like a successor/fixer of Pascal. It doesn't fall down the OO hole that so many others did. It has type casting, dynamic arrays, parametric polymorphism in both functions and data structures, is much less noisy (and in my opinion far more skimmable), more useful built-in primitive data structures like associative arrays and matrices, custom allocators, function overloading, reflection, etc.
You can find odds and ends of these things in other Pascal successors like Delphi, Oberon and Object Pascal. Truth is though, I never found these languages compelling. Why? Because none of them were anywhere close to being the same kind of simplicity as Pascal, and they were too wrapped up in flashy, trendy things that went out of style. Where Odin wins out is that it distinctly lacks the 90's OO craze hangover, and it never feels particularly more complicated or bloated. It's an audaciously tasteful proposition for a language. A C replacement? No, not really. But as a C++ programmer who's fed up with the lack of things like structure introspection and ergonomic sum types, I'm keeping a very close eye on Odin.
Thank you for the kind words regarding Odin! So Odin is in the family of Pascal _but_ I've tried my best to design it in such a way that it does "fix" most of the problems of C (since I am/was a C programmer), and make it _feel_ good to a C programmer when programming in the language.
My view is that the core of Pascal was actually the correct place to start rather than the core of C. C won out of Pascal purely because the original Pascal didn't fix its problems quick enough, and all of the successors also tried to focus on other fancier things like OOP or GC or whatever. C still remained "basic" and its preprocessor allowed for enough extensions for lacking language features, whilst not adding any of those fancier things.
For Odin, I tried to take the lessons of what I and others were emulating in C and just make them core constructs. Odin initially didn't have many of the constructs it has now such as parametric polymorphism or explicit procedure overloading, but all of them came about as a result of solving the problems people used the preprocessor for or other new features. For example, the explicit procedure overloading came about seeing how people use the (relatively new) C11 `_Generic` feature, and realizing that they were trying to emulate this aspect pretty much.
Odin also took a lot of the GNU C extensions and incorporated them directly (some of which are not in the latest version of C): `0b` literals, nested procedures (but not scope capturing), `type_of`, `case` ranges (`..<` and `..=` in Odin to be more explicit about the range bounds), array initializes with ranges, unnamed structs/unions, empty structs, and so much more.
Odin isn't a C++ alternative by any stretch, but I have seen a lot of C++ programmers really like it because it feels like it has just enough to make them feel at home whilst still have the control and more explicitness that C offers.
Perhaps not modern C++, but I would absolutely place it in the same weightclass as CFront and C++98 (albeit with less bugs and more ergonomics than those). I know you've placed the language adjacent to gamedev, so an appropriate metaphor, I feel like Odin is up to the task of making something with the complexity of a Goldsrc game, or a Dreamcast game. I feel like I could churn out half a million lines of high density soft real-time code quite happily.
Excited to see how it evolves through the years. Keep up the good work!
I feel like the lack of marketing push is for two reasons. One is that it feels like Odin simply doesn't desire the kind of attention the other two languages have. Two is...I can't speak for Rust, but I feel like Zig punches well above its weight because of comptime, privileged support for Result <T, E> in the form of error unions, and having a realistic roadmap for porting C code thanks to translate-c and its build system.
From what little I've seen of Odin, it doesn't have anything in particular that's especially headline-grabbing. However, Odin does have one thing that Zig doesn't, and it's that the language is considered "complete" despite its git repository being newer than Zig by a year. When it comes to programming languages, I do feel like there's something to be said for ease-of-implementation, and although Zig _feels_ simple from a feature-set point of view, I imagine it has a much higher bar to clear in terms of implementation complexity.
It's not "hypeable" like Zig or Rust mainly because it doesn't have any "killer features" but rather is a very pragmatic language by design. The people Odin attracts are also not the types of people to evangelize Odin either, since they are not there for the hype-train but to actually program.
So if you can help us find a way to market Odin itself without lying or exaggerating or overblowing minor features, then that would be very much obliged. It's a lot harder than you think.
As for "1.0", we have never worked to a timeframe for anything nor any sort of roadmap. The reason being is that we do not want to give false promises/hope about anything. Roadmaps are purely for advertisement, and the problem is, we don't even work to one so why present one? The other problem is that for "1.0", the language itself is well known: it's pretty much what you see today. But "1.0" for the general tooling? Now that's a harder question. We have plans but since everything is being worked on as we go (mostly volunteers), we cannot say when things will be finished. The biggest project at the moment is `core:os/os2`, the replacement for the `core:os` package. `core:os` was the first package ever written for Odin and it's absolutely dreadful and needs replacing. And that's what we've been doing with `core:os/os2`, slowly. And when it is ready, we will tell people many months in advance when we will make it the official one. This will be a breaking change, but probably the last biggest one for Odin.
> Delphi, Oberon and Object Pascal [..] I never found these languages compelling. Why? Because none of them were anywhere close to being the same kind of simplicity as Pascal
Agree. Oberon comes close, but has other orthodoxies like upper-case keywords, and it lacks the low-level support of e.g. Delphi. I spent a lot of time with extending Oberon, but backward compatibility prohibited some features I thought were necessary. My forthcoming Micron language is this kind of "better Pascal" you mentioned; essentially it's an Oberon withouth orthodoxies and with the power of C (without its disadvantages); there are language levels from minimal, stack-less systems, up to dynamic dispatch and optional garbage collection. See https://github.com/rochus-keller/micron/.
Did you take a look at Ada as replacement for Pascal ? With the 'gnat' compiler and some doc (https://www.adaic.org/learn/) I think you can find what you are looking for.
I think Nim is much more of a pascal successor than Go ; It retains some of the syntax and feel, although it uses Python style indentation instead of begin/end.
It is by no means pascal-simple - although the subset used by 95% of programs is.
It does have everything you need including macros, unsafe access, minimal OO but these are almost exclusively used by library developers.
Odin really hits the sweet spot for everything you would want from a language for the game dev and game-dev-adjacent space in terms of simplicity, convenience, and speed. I think a major design decision of the language that will make or break it for users is the fact that the language gives you common features instead of giving you the means of abstraction to make those features yourself. For example, instead of preprocessor macros you get the `when` clause for conditional compilation because in Bill's estimation, that's one of the only real needs for macros. The same goes for data structures. Odin gives you the certified classics like dynamic arrays and maps but doesn't give you a whole lot to make your own custom data structures (it's possible, just not encouraged by the language design). All in all, I think if you want to make an application with a language that has batteries included and you don't need a lot more than that, Odin is nearly flawless.
> but doesn't give you a whole lot to make your own custom data structures
For anyone unfamiliar with Odin that might misinterpret this, Odin has structs and parametric polymorphism for those structs. What it does not have is operator overloading or methods (which also means no constructors or destructors). In this sense, its product types are like ocaml's, only without methods too. Odin is not object oriented.
Odin truly feels like a C successor, and as someone who likes Go, it appeals to me a lot more than Zig or Rust. Partly because it took inspiration from the Pascal, Delphi, Oberon branch, same as Go.
I don’t particularly enjoy working on the types of problems Zig or Rust aim to solve. I spend the majority of my time working at layer 4, and Go makes it immensely enjoyable. But sometimes I want a bit more control over the hardware and don’t want to pay the cost of a GC. Odin feels just right.
In my case, the assortment of syntactic features like OOP, compile-time macros, or even the borrow checker suck all the fun out of programming. That’s why I still enjoy writing C programs, footguns and all.
I've started experimenting with Odin for some personal projects and it's been great. The built-in vendored libraries make creating certain programs trivial. For example, just `import rl "vendor:raylib"` and you can use `rl.InitWindow(800,600,"Test")`. No need to install Raylib, add to path or use special linker directives, just `odin build .`!
Also I think Odin struck the right balance of features while trying to keep to the spirit of C.
I've been using Odin for the last ~6 months, wrote a 15k loc project and it's been an absolute pleasure. This is my first low level language after 10 years of web dev, and it feels much higher level than it is, while giving you the control and performance of a language like C.
I like pretty much every choice that has been taken when designing the language, except maybe the lack of namespaces, which can be solved anyway with prefixes.
The lack of OOP features is the best part for me, it's rewiring my brain in a good way and I can now also reason much better about RDBMS schemas. Data oriented design is the most helpful approach I've stumbled upon in my career.
As a completely incidental observation (and maybe related to the article from a few days ago considering the importance of language skills compared to math skills for software development), I'm interested in what people choose to capitalize when developing languages. With c, lowercase seems to be the default, signifying variables or function calls. Adding inheritance in c++ leads to Proper Nouns like classes being capitalized, while their instances are often lowercase. This communicates a subtle "feel" for the language, meta information about what's being accomplished.
Capitalizing method calls (`rl.InitWindow()`) seems to place the importance on the Method being called, but at first glance (ASP, or Go off the top of my head) it muddies the waters. If this isn't clear, consider that capitalizing ALL code would reduce clarity as all letter shapes are now essentially the same (a box).
I spend most of my time in c, c++, ruby, and javascript, but maybe I should try to do a personal project in Go (or Odin) for this reason alone.
I believe most of this is language designers picking their personal preference and then that percolating down through history.
The original UNIX folks really love lowercase. Executables are lowercase, most file names are lowercase, file extensions are, etc. That extends to C where DMR and Ken Thompson chose lowercase names for keywords, built-in types, and standard library functions. If I remember right, Thompson uses all lowercase in most of his communications too, so I suspect it comes from him. Or maybe it was a flex because the PDP-11 could do lowercase when some other early computers didn't support it at all?
The early Pascal compilers from Niklaus Wirth and friends appear to be all caps, probably because that's all the machines supported. The language itself generally isn't case sensitive. (I say "generally" because there are many flavors of Pascal.)
When Anders Hejlsberg created Turbo Pascal (which is also case-insensitve), he introduced a convention of lowercase for keywords what we now call PascalCase for function and type names and (judging by the Wikipedia article) a mixture of PascalCase and camelCase for variables.
Perhaps because Straustrup built on C but is a Dane like Hejlsberg, he picked a mix for C++: camelCase function and variable names with PascalCase type names.
These conventions then flowed down through time. Java was heavily inspired by C++ and takes the same convention. C# is another Hejlsberg creation and follows his preferences. JavaScript follows Java. (It must annoy Hejlsberg to no end that his third baby TypeScript breaks with his own convention.)
In this case, I believe the capitalization is a hold-over from raylib's c library, Odin doesn't appear to put any preference?
In Go it has a specific meaning: starting an identifier with a capital causes it to be exported for use in other packages. Identifiers with a starting lowercase char are package private.
Apologies if this is explaining what you already know...
Odin itself does not care what naming conventions you use. Use whatever you prefer.
For Odin native libraries, we usually for the convention of `snake_case` for variables and procedures and `Ada_Case` for types. However for anything that is third-party/foreign, we try to keep to the same convention as the original library to make it easier to people reference the original documentation, as well as not have any of the problems that certain naming conventions cannot be translated to another. So the raylib code uses the original raylib naming conventions because of the reasons I described.
Sticking to an library style is a way to go. It's so much friction to use python library wrappers which try to hammer original style into a snake_case.
Nim has solved this in a very practical way, which works great - case insensitive except 1st letter, and underscore insensitive. So hello_world and helloWorld and hello___wOrlD are the same identifier, though HelloWorld and hello_world are not.
Many people complain that this is horrible, but not people who have actually tried it. It works very well, lets you bridge over differences in C++ library conventions, Unix C conventions and Microsoft conventions in a project that interfaces all of them, without getting users upset. (There’s more to it - consistency for some identifier can be enforced, there’s a smart source reformatted, and more)
snake_case is just more readable overall. PascalCase and/or camelCase are okay in moderation and add a kind of emphasis, which is why e.g. Rust uses PascalCase for types (other than core built-in ones) and enum case constructors. SCREAMING_SNAKE_CASE is ok for even rarer things that should stand out - C/C++ uses it for preprocessor macros, Rust for program constants and global variables. Ada_Case is rare and mostly shows up in languages with case-insensitive identifiers, like Ada itself.
"originated as a re-engineering of C++"
"influenced by Java, Python, Ruby, C#, and Eiffel"
"design by contract, ranges, built-in container iteration concepts, and type inference"
"array slicing, nested functions and lazy evaluation."
"Java-style single inheritance with interfaces and mixins"
"function overloading and operator overloading"
"supports five main programming paradigms" (including OOP)
... et cetera
Though it does support things like in-line assembly and the like, I'm sure most C programmers would pass on it, as a C-alternative, based on those factoids.
Once, on a previous account, he actually replied to me. It's like a kid going to guitar center and the guy who replaces your strings is Axl Rose.
If you're on here, Walter, you're my hero. I also once interacted with Brendan Eich, who I admire as much for his role in web history as for his activism.
> That D exposes a curated subset of D doesn’t make it a C alternative,
But why? You comment does not clarify what does this subset lack which prevents it being used as a C alternative. The intention is explicitly stated and the "spirit" argument is weak as overly subjective.
C is liked particularly, even considering all its shortcomings, for being a relatively limited language in scope, being raw but flexible.
D's scope seems to go far beyond what your average C programmer would want in a language; "use only 15% of the language and you'll be fine" (paraphrasing: "use only the 'better-C' subset", if that is what you meant, and it does seem to be a subset of D) seems a weird proposition; it still complicates things, as in collaboration, idiomatic feel and look of code, the amount of knowledge required to be competent in the language, complexity of a compiler implementation, portability of code etc... and by that logic you'd have to prefer C++ over C as well (since a lot of C is valid C++), or prefer C plus one safety feature added over C; but the "rawness"/limited scope/small size/procedural nature of C is what's appealing for many to begin with.
I for one think that a proper C replacement (C's strength also being the simplicity in which to implement a compiler for example, being the reason it's so ubiquitous in the embedded world) will be a much more limited proposition than D is.
RAII
Full metaprogramming
Nested functions, nested structs, delegates and lambdas
Member functions, constructors, destructors, operating overloading, etc.
...
Where to draw the line will be different person to person, but D doesn't seem to be a language "in the spirit of C", or a "modern version of it", at all.
Viewing it as a C++ alternative makes much more sense. A `Better-C` "limit yourself to a subset of the language" compiler flag doesn't change that much.
I wouldn't like RAII, and why I didn't add it to Odin. It's not a feature C programmers want. And you've just agreed that C don't want ctors/dtors, which is necessary for RAII to work... ctors/dtors are bad for their own reasons (mainly because you cannot handle error cases except through exceptions, which many people disable too).
If you aim to be both a C alternative and C++ alternative, in reality you are just a C++ alternative because you haven't understood why people prefer C over C++. Therefore D is a C++ alternative and that's what it was always trying to be, even with "BetterC".
Most C programmers I know pretty much do that. I use C11 just for the atomics and that is it. And I know many C programmers who still use C89/C90 exclusively.
Odin seems to strike a really interesting balance between simplicity and practicality, especially for game development. I like the idea of having “batteries included” without too much abstraction getting in the way. For those who have used both Odin and Go, how do you feel about the differences in day-to-day development? Are there any features in Odin that you wish Go had, or vice versa? Would love to hear more real-world experiences!
I mean, the biggest difference is that Go has a GC and Odin doesn't. And each's ecosystem reflects that... In practice they're simply not used for the same types of software.
I am currently limiting myself to 500 lines of (particle engine) code while listening to visual artists talking about their workflow in UE5 or Houdini, and Odin+Raylib are lovely to work in.
GingerBill has shouted out Go, but Odin doesn't particularly feel like a Go flavo(u)r.
been playing around with odin and honestly the ease of getting started feels way better for me than most c-like stuff ever has. you ever think these smaller pain points keep more folks from switching than big technical features?
I haven't read the article yet, but this seems to conflate compile time evaluation with metaprogramming. Not all comptime evaluation is metaprogramming. I would argue the majority of comptime programming as it is used in Zig isn't even metaprogramming. Metaprogramming is a paradigm where there source or target data structure is primarily the language you're programming in. comptime evaluation of expressions that could be runtime evaluated is not that. I would argue that comptime evaluation of expressions that return comptime only values (like types) is not even inherently that.
Where you start to see actual metaprogramming in Zig is in functions like @typeInfo, @alignOf, @offsetOf, which actually let you operate on language constructs (ie: looping over the fields of a struct). This is not extremely out of the ordinary, but it's not done "as much as possible".
Another place that metaprogramming shows up in Zig is code generation using the build system. I've never done this, and I would argue this is usually recommended to be done as little as possible, rather than as often as possible.
Edit: I read the article, and while I think that the author was wrong about Zig pushing metaprogramming "as much as possible", they were fairly accurate in how it is used in the rest of the article, like for serialization. The thing is, most of my programs are not serialization. I use serialization as a means to do other things.
IMO it's one of Zig's advantages over C (text substitution macros are both too powerful and not powerful enough). If you're using Zig without metaprogramming, you're leaving a useful (if advanced) tool on the table.
C's preprocessor not being powerful enough is less a problem with text-substitution macros, more that they're not allowed to expand recursively which was an intentional design choice. There are some hacks you can do to get around it, and people have done cool things[1] within the limited space those hacks grant you, but there's a reason many C projects with extensive metaprogramming just use an external macro language (which is also just text-substitution).
IMO AST Macros are an even bigger problem than text substitution. Debugging metaprogramming of any kind past a certain point of complexity is a royal pain in the ass (even in a Lisp, Forth or Prolog), but AST explorers are next to useless for complicated logic problems that involve needle in a haystack searches of side effects. If you're dealing with a large AoS of heterogeneous SoAs which influence each other to shuffle around, and most of the related code and the structures themselves are generated via AST macros, you better be really comfortable with assembly analysis and debugger scripting.
I can't comment about everyone, but I use it a lot for building libraries and such. I just recently built a database ORM, but since their metaprogramming is used for their generics I've run across it a lot just for those case.
i think "using comptime" as a definition of metaprogramming is not really accurate... for example, i think calling this metaprogramming is really stretching it:
var x: [sqrt(LENGTH)]f32 = undefined
i think calling "instantiating a generic type" meta-programming is weak, since you're not doing any of the metaprogramming yourself, though i would concede that if debugging is the concern there is a point there.
Depends on the project, the general recommendation is to use metaprogramming like salt: just a pinch to add some flavor. Newcomers sometimes go bonkers with it though.
Can't comment on RTTI, but lack of conditional imports are indeed an annoyance but I'm willing to put up with it because of all the other niceties in the language.
There is compile time type introspection in Odin, it's just not that easy to use on purpose. But why do you not want RTTI? One of the reasons I wanted it over CTTI is because it's a fixed cost rather than an exponential cost—at both compile-time and run-time.
People who want CTTI is because they think it will produce better code because it is specialized for that type, and that is partially true, but also it will produce a hell of a lot more code. The canonical example of what I mean is the difference between doing something like `core:fmt` in Odin, which is a fixed cost at both compile-time and run-time, and then doing something closer to `std::format` in C++ (or other similar things in other languages) which will do a specialized procedure for each set of argument types. The former might be a huge initial cost if you only have a single type you want to print, but that cost is always the same regardless of many more types you add, it's also easier to debug. The latter is a small initial cost per type, and when the types get more and more complex, you also produce more and more code, which in turn increases the compiling time and binary/executable size.
As for the conditional imports, we did use to allow them but we found that what people were doing with them was kind of missing the point of the platform-specific features of the `package` system, and their code was always better if it actually utilized the package system correctly. There were some other quirks with the conditional imports which did confuse people because they didn't realize how things had to be executed (to allow for out-of-order type checking) and just disallowing it in the first place just solves that too (as a consequence, not as a goal).
It's not. However it is safer than C by default due to things like bounds-checking on arrays, slices (ptr+len), tagged unions, distinct typing for many things, an actual enum type, numerous checks for things like missing switch cases, and my more.
It's not trying to be memory safe, but rather try and catch many common mistakes that C does not catch easily.
As for use-after-free, I'd argue that is more of a problem with the memory allocation strategy in a language like C or Odin. And a change to something like an Arena like memory allocation strategy or something else reduces issues like that by a hell of a lot. `malloc`/`free` like approaches to memory allocation make use-after-free a lot more common because it making you micromanage allocations on a per-value level rather than on a per-shared-lifetime level. It's rare a single value has a unique lifetime, and I'd argue never in many projects.
One of the things I like about ObjC is that ARC is really really well done. The only time I care about memory management in ObjC is with cyclic references (eg: A->B and B->A). Those are about as rare as hen's teeth, and memgraph points them out if they ever do raise their head.
ObjC is pretty much the sweet spot for me in terms of language complexity and cognitive load over C, while providing so much more. It's really a shame that a lot of people (and I'm not pointing any fingers at anyone specifically) can't get past the [..] syntax, which comes from making ObjC a pure superset of C.
The language creator strongly suggests using arenas and zero-is-initialization. That's a programming paradigm that completely avoids having to keep track of zillions of small memory allocations, so the mechanisms needed to manage that are less important.
A C alternative means a language that will last for 50 years, whereas this seems more like "whatever's popular by way of LLVM". I can see some real smart stuff coming out of languages like Zig and Rust, where Odin seems just to follow along.
Seems needlessly harsh and also misplaced in some way. Zig is super non-ergonomic to any C-developer, and its explicitness at all costs is also non-C-like (meaning a rather big shift for someone actually liking C). Rust is a completely different beast altogether.
Odin is a rather simple, performant, pragmatic, procedural language, fixing especially things in C with regards to its type system and infrastructure (such as packages), adding niceties such as `defer` while being at it. I, as a C programmer, have it far higher up my list of languages to try than Zig or Rust by a rather large margin.
btw: "C alternative means a language that will last for 50 years" seems a snide that could be applied to any language less than 20 years old? I'm not sure what that's concretely meant to criticize here? Is Zig more a 50-year language than Odin, if so how? Odin is used for rather serious commercial products at JangaFX btw: https://jangafx.com/ and is quite beloved by some people using it.
I have long been aware of that particular user of Odin, after all the creators mention it frequently. The fact remains that the US government has warned against the use of languages such as Odin [1]. As such, it is competing in the extremely small niche of "languages best suited for embedded computing and operating systems". Suffice to say that most of its users likely do not use it for that. Finally there is the matter of trust. A while ago I was shopping around these new languages that have sprouted out of LLVM and watched a few talks from the creators of various languages. The Zig team were both ambitions and clear in their presentation. They gave me the impression of an experienced and motivated team. By contrast the Odin presentation I saw was utterly directionless and filled with fluff. I like to think I have a good nose for BS, and Odin trips it. That great wall of random corporate logos of companies which don't use Odin on their website doesn't help. Upon investigating, I find that the creator of the language is also a developer at JangaFX, so is either using the Odin website to advertise his own software, or hoping to obtain clout by mentioning large companies as if they used Odin when they do not. You might think I'm being overly critical, but I've learned the hard way to avoid things like this. It's a mighty pain depending on something which ends up abandoned or unused. The Zig compile supports multiple codegen backends, compiling C/C++ code, and easy cross-compilation. It is a considerable feat of engineering and shows a lot of dedication on the part of the creators. I can see nothing comparable on the Odin front.
Additionally, I don't think a C replacement should be immediately intuitive to someone who has only ever used C. To entice people away from on of the most popular and stable programming languages ever created, you must offer more than an incremental improvement. There needs to be a paradigm shift, which necessitates some degree of learning on the part of the developer.
I don't understand the point of this. When I say "Go flavour" I thought it would have lightweight threads like Go, but there is no mention of that in the description page. So it's another uninteresting curly brace language as far as I can tell. I'd rather use one with more traction.
"go flavour" refers to the similarity in the design philosophy, and some of the features. That said, it's still not Go.
For example, "errors as values" is a point that Odin makes, but it does make it in a slightly different light from Go. Whereas Go has an `error` type that encompasses all errors, Odin does not. Instead, it treats some types (booleans, enums, unions) as "special", in that they support things like `or_return`, which are typically your error propagation statements. Oh yeah, `or_return` is another big point, it does simplify a lot of `if err != nil { return err }` type of code.
And another big similarity to Go is the declaration syntax. It was inspired by one of Rob Pike's (iirc) comments on twitter about how they should have used a different syntax for Go instead.
From personal experience though, there are some things in Odin that I wish Go had. Its features play along together so nice, and it's so satisfying having three different language features come together in a nice logically-coherent simple way. That said, I don't think Odin is capable of replacing Go. Things like server-side logic and lightweight threads are probably where Go still excels at and beats Odin.
For systems-level programming I'd pick Odin though.
I just don't see the surface syntax as mattering that much. When I see "Go", I think lightweight threads, channels, and GC. Stuff like the declaration syntax is way down the list. Thanks though.
For me, I don't really look at Odin as a successor/fixer of C. There are other languages that can make a better case for that[1][2]. Instead, I look at it more like a successor/fixer of Pascal. It doesn't fall down the OO hole that so many others did. It has type casting, dynamic arrays, parametric polymorphism in both functions and data structures, is much less noisy (and in my opinion far more skimmable), more useful built-in primitive data structures like associative arrays and matrices, custom allocators, function overloading, reflection, etc.
You can find odds and ends of these things in other Pascal successors like Delphi, Oberon and Object Pascal. Truth is though, I never found these languages compelling. Why? Because none of them were anywhere close to being the same kind of simplicity as Pascal, and they were too wrapped up in flashy, trendy things that went out of style. Where Odin wins out is that it distinctly lacks the 90's OO craze hangover, and it never feels particularly more complicated or bloated. It's an audaciously tasteful proposition for a language. A C replacement? No, not really. But as a C++ programmer who's fed up with the lack of things like structure introspection and ergonomic sum types, I'm keeping a very close eye on Odin.
[1] - https://c3-lang.org/
[2] - https://harelang.org/
Thank you for the kind words regarding Odin! So Odin is in the family of Pascal _but_ I've tried my best to design it in such a way that it does "fix" most of the problems of C (since I am/was a C programmer), and make it _feel_ good to a C programmer when programming in the language.
My view is that the core of Pascal was actually the correct place to start rather than the core of C. C won out of Pascal purely because the original Pascal didn't fix its problems quick enough, and all of the successors also tried to focus on other fancier things like OOP or GC or whatever. C still remained "basic" and its preprocessor allowed for enough extensions for lacking language features, whilst not adding any of those fancier things.
For Odin, I tried to take the lessons of what I and others were emulating in C and just make them core constructs. Odin initially didn't have many of the constructs it has now such as parametric polymorphism or explicit procedure overloading, but all of them came about as a result of solving the problems people used the preprocessor for or other new features. For example, the explicit procedure overloading came about seeing how people use the (relatively new) C11 `_Generic` feature, and realizing that they were trying to emulate this aspect pretty much.
Odin also took a lot of the GNU C extensions and incorporated them directly (some of which are not in the latest version of C): `0b` literals, nested procedures (but not scope capturing), `type_of`, `case` ranges (`..<` and `..=` in Odin to be more explicit about the range bounds), array initializes with ranges, unnamed structs/unions, empty structs, and so much more.
Odin isn't a C++ alternative by any stretch, but I have seen a lot of C++ programmers really like it because it feels like it has just enough to make them feel at home whilst still have the control and more explicitness that C offers.
> Odin isn't a C++ alternative by any stretch
Perhaps not modern C++, but I would absolutely place it in the same weightclass as CFront and C++98 (albeit with less bugs and more ergonomics than those). I know you've placed the language adjacent to gamedev, so an appropriate metaphor, I feel like Odin is up to the task of making something with the complexity of a Goldsrc game, or a Dreamcast game. I feel like I could churn out half a million lines of high density soft real-time code quite happily.
Excited to see how it evolves through the years. Keep up the good work!
Where can I follow Odin's progress other than the blog? It doesn't seems to have any social media presence.
And what sort of time frame in terms of 1.0? I found Odin lacks the marketing push from Zig or Rust.
I feel like the lack of marketing push is for two reasons. One is that it feels like Odin simply doesn't desire the kind of attention the other two languages have. Two is...I can't speak for Rust, but I feel like Zig punches well above its weight because of comptime, privileged support for Result <T, E> in the form of error unions, and having a realistic roadmap for porting C code thanks to translate-c and its build system.
From what little I've seen of Odin, it doesn't have anything in particular that's especially headline-grabbing. However, Odin does have one thing that Zig doesn't, and it's that the language is considered "complete" despite its git repository being newer than Zig by a year. When it comes to programming languages, I do feel like there's something to be said for ease-of-implementation, and although Zig _feels_ simple from a feature-set point of view, I imagine it has a much higher bar to clear in terms of implementation complexity.
So Odin the language in-itself is effectively done. But of course the core library, vendor library, tooling, etc are still very much being improved.
The reason for the lack of "social media presence" is because Odin is kind of weird to market for: https://www.gingerbill.org/article/2024/09/08/odin-weird-to-...
It's not "hypeable" like Zig or Rust mainly because it doesn't have any "killer features" but rather is a very pragmatic language by design. The people Odin attracts are also not the types of people to evangelize Odin either, since they are not there for the hype-train but to actually program.
So if you can help us find a way to market Odin itself without lying or exaggerating or overblowing minor features, then that would be very much obliged. It's a lot harder than you think.
As for "1.0", we have never worked to a timeframe for anything nor any sort of roadmap. The reason being is that we do not want to give false promises/hope about anything. Roadmaps are purely for advertisement, and the problem is, we don't even work to one so why present one? The other problem is that for "1.0", the language itself is well known: it's pretty much what you see today. But "1.0" for the general tooling? Now that's a harder question. We have plans but since everything is being worked on as we go (mostly volunteers), we cannot say when things will be finished. The biggest project at the moment is `core:os/os2`, the replacement for the `core:os` package. `core:os` was the first package ever written for Odin and it's absolutely dreadful and needs replacing. And that's what we've been doing with `core:os/os2`, slowly. And when it is ready, we will tell people many months in advance when we will make it the official one. This will be a breaking change, but probably the last biggest one for Odin.
> Delphi, Oberon and Object Pascal [..] I never found these languages compelling. Why? Because none of them were anywhere close to being the same kind of simplicity as Pascal
Agree. Oberon comes close, but has other orthodoxies like upper-case keywords, and it lacks the low-level support of e.g. Delphi. I spent a lot of time with extending Oberon, but backward compatibility prohibited some features I thought were necessary. My forthcoming Micron language is this kind of "better Pascal" you mentioned; essentially it's an Oberon withouth orthodoxies and with the power of C (without its disadvantages); there are language levels from minimal, stack-less systems, up to dynamic dispatch and optional garbage collection. See https://github.com/rochus-keller/micron/.
Did you take a look at Ada as replacement for Pascal ? With the 'gnat' compiler and some doc (https://www.adaic.org/learn/) I think you can find what you are looking for.
Isn't Go the modern successor of Pascal? It certainly didn't fall down the OO hole.
I think Nim is much more of a pascal successor than Go ; It retains some of the syntax and feel, although it uses Python style indentation instead of begin/end.
It is by no means pascal-simple - although the subset used by 95% of programs is.
It does have everything you need including macros, unsafe access, minimal OO but these are almost exclusively used by library developers.
First it needs to catch up to some Pascal features like real enumerated types, no iota/const dance.
Hard disagree the simplicity of Pascal, is what made it unusable outside the original goal to learn programming.
Instead we ended up with UCSD Pascal, Object Pascal, TMT Pascal, Quick Pascal, VMS Pascal, Delphi and what not.
By the time it came to be, ISO Extended Pascal was largely irrelevant, outside some UNIX compilers that supported it.
The Borland linage, after taking over Apple's design, which had input from Niklaus Wirth, is my favourite, then their management messed up.
In an ideal world, Modula-2 or Ada would have taken over, sadly no big name OS vendor, ever felt like adopting them.
As for Oberon, when I came to learn it, Oberon-2 was already out, eventually Component Pascal and Active Oberon were much more interesting to me.
While I appreciate Niklaus Wirth work, I was never a fan of the minimalism he tried to pursue with Oberon-07. Then rather use Go.
In the end, nothing of this will matter in the age of AI assisted tooling and code generation.
Arguing what is the best language is getting akin to argue about Assembly language syntax, when most people are using optimizating compilers.
Odin really hits the sweet spot for everything you would want from a language for the game dev and game-dev-adjacent space in terms of simplicity, convenience, and speed. I think a major design decision of the language that will make or break it for users is the fact that the language gives you common features instead of giving you the means of abstraction to make those features yourself. For example, instead of preprocessor macros you get the `when` clause for conditional compilation because in Bill's estimation, that's one of the only real needs for macros. The same goes for data structures. Odin gives you the certified classics like dynamic arrays and maps but doesn't give you a whole lot to make your own custom data structures (it's possible, just not encouraged by the language design). All in all, I think if you want to make an application with a language that has batteries included and you don't need a lot more than that, Odin is nearly flawless.
> but doesn't give you a whole lot to make your own custom data structures
For anyone unfamiliar with Odin that might misinterpret this, Odin has structs and parametric polymorphism for those structs. What it does not have is operator overloading or methods (which also means no constructors or destructors). In this sense, its product types are like ocaml's, only without methods too. Odin is not object oriented.
Odin truly feels like a C successor, and as someone who likes Go, it appeals to me a lot more than Zig or Rust. Partly because it took inspiration from the Pascal, Delphi, Oberon branch, same as Go.
I don’t particularly enjoy working on the types of problems Zig or Rust aim to solve. I spend the majority of my time working at layer 4, and Go makes it immensely enjoyable. But sometimes I want a bit more control over the hardware and don’t want to pay the cost of a GC. Odin feels just right.
In my case, the assortment of syntactic features like OOP, compile-time macros, or even the borrow checker suck all the fun out of programming. That’s why I still enjoy writing C programs, footguns and all.
When I first saw Odin, I wrote down a list of everything I didn't think I'd like.
After several thousand lines, it proved all of my major worries incorrect, and has been an absolute pleasure.
It has since replaced my usage of Go, which I had been using since release.
I would highly recommend giving it a proper shot!
I'm kinda curious, you mind sharing some of the things you thought you didn't like?
I took a good hard look at everywhere I may have stored it, but I believe I lost the original list after formatting.
I remember believing these were important:
- methods (turned out I mainly wanted working intellisense, which Odin does even without methods)
- a package manager (still a gripe, but git submodules do the trick somewhat)
- expressions (so I could assign the result from a `switch` statement to a variable for instance, but I can use an #inline proc if I _really_ want to)
- private by default (I had forgotten how many times I wanted to use something private from a library, and had to fork it instead)
- - although possible to make something private in Odin, nowadays I'd rather things be prefixed with underscores instead
Also, here are my list of things I'd still prefer changed, but are less important: https://forum.odin-lang.org/t/what-features-of-odin-do-you-d...
Odin is public by default.
I've started experimenting with Odin for some personal projects and it's been great. The built-in vendored libraries make creating certain programs trivial. For example, just `import rl "vendor:raylib"` and you can use `rl.InitWindow(800,600,"Test")`. No need to install Raylib, add to path or use special linker directives, just `odin build .`!
Also I think Odin struck the right balance of features while trying to keep to the spirit of C.
I've been using Odin for the last ~6 months, wrote a 15k loc project and it's been an absolute pleasure. This is my first low level language after 10 years of web dev, and it feels much higher level than it is, while giving you the control and performance of a language like C.
I like pretty much every choice that has been taken when designing the language, except maybe the lack of namespaces, which can be solved anyway with prefixes.
The lack of OOP features is the best part for me, it's rewiring my brain in a good way and I can now also reason much better about RDBMS schemas. Data oriented design is the most helpful approach I've stumbled upon in my career.
Here is the website: https://odin-lang.org/ - which was not obvious.
As a completely incidental observation (and maybe related to the article from a few days ago considering the importance of language skills compared to math skills for software development), I'm interested in what people choose to capitalize when developing languages. With c, lowercase seems to be the default, signifying variables or function calls. Adding inheritance in c++ leads to Proper Nouns like classes being capitalized, while their instances are often lowercase. This communicates a subtle "feel" for the language, meta information about what's being accomplished.
Capitalizing method calls (`rl.InitWindow()`) seems to place the importance on the Method being called, but at first glance (ASP, or Go off the top of my head) it muddies the waters. If this isn't clear, consider that capitalizing ALL code would reduce clarity as all letter shapes are now essentially the same (a box).
I spend most of my time in c, c++, ruby, and javascript, but maybe I should try to do a personal project in Go (or Odin) for this reason alone.
I believe most of this is language designers picking their personal preference and then that percolating down through history.
The original UNIX folks really love lowercase. Executables are lowercase, most file names are lowercase, file extensions are, etc. That extends to C where DMR and Ken Thompson chose lowercase names for keywords, built-in types, and standard library functions. If I remember right, Thompson uses all lowercase in most of his communications too, so I suspect it comes from him. Or maybe it was a flex because the PDP-11 could do lowercase when some other early computers didn't support it at all?
The early Pascal compilers from Niklaus Wirth and friends appear to be all caps, probably because that's all the machines supported. The language itself generally isn't case sensitive. (I say "generally" because there are many flavors of Pascal.)
When Anders Hejlsberg created Turbo Pascal (which is also case-insensitve), he introduced a convention of lowercase for keywords what we now call PascalCase for function and type names and (judging by the Wikipedia article) a mixture of PascalCase and camelCase for variables.
Perhaps because Straustrup built on C but is a Dane like Hejlsberg, he picked a mix for C++: camelCase function and variable names with PascalCase type names.
These conventions then flowed down through time. Java was heavily inspired by C++ and takes the same convention. C# is another Hejlsberg creation and follows his preferences. JavaScript follows Java. (It must annoy Hejlsberg to no end that his third baby TypeScript breaks with his own convention.)
In this case, I believe the capitalization is a hold-over from raylib's c library, Odin doesn't appear to put any preference?
In Go it has a specific meaning: starting an identifier with a capital causes it to be exported for use in other packages. Identifiers with a starting lowercase char are package private.
Apologies if this is explaining what you already know...
Odin itself does not care what naming conventions you use. Use whatever you prefer.
For Odin native libraries, we usually for the convention of `snake_case` for variables and procedures and `Ada_Case` for types. However for anything that is third-party/foreign, we try to keep to the same convention as the original library to make it easier to people reference the original documentation, as well as not have any of the problems that certain naming conventions cannot be translated to another. So the raylib code uses the original raylib naming conventions because of the reasons I described.
Sticking to an library style is a way to go. It's so much friction to use python library wrappers which try to hammer original style into a snake_case.
Nim has solved this in a very practical way, which works great - case insensitive except 1st letter, and underscore insensitive. So hello_world and helloWorld and hello___wOrlD are the same identifier, though HelloWorld and hello_world are not.
Many people complain that this is horrible, but not people who have actually tried it. It works very well, lets you bridge over differences in C++ library conventions, Unix C conventions and Microsoft conventions in a project that interfaces all of them, without getting users upset. (There’s more to it - consistency for some identifier can be enforced, there’s a smart source reformatted, and more)
That's a method from Raylib, a C library which has Odin bindings. For all libraries, Odin follows the original library's style.
The Odin convention is Pascal case (lower_case_procedures, Capitalized_Enums_And_Structs).
It's technically `Ada_Case` that we use, because I like reading it.
snake_case is just more readable overall. PascalCase and/or camelCase are okay in moderation and add a kind of emphasis, which is why e.g. Rust uses PascalCase for types (other than core built-in ones) and enum case constructors. SCREAMING_SNAKE_CASE is ok for even rarer things that should stand out - C/C++ uses it for preprocessor macros, Rust for program constants and global variables. Ada_Case is rare and mostly shows up in languages with case-insensitive identifiers, like Ada itself.
FWIW, another take on "C Alternative" is the D programming language:
https://wiki.dlang.org/Tutorials
Comparatively mature, there's even a freeware book which is quite good:
http://www.ddili.org/ders/d.en/index.html
I always thought it was more akin to a C++ than a C alternative, and reading https://en.wikipedia.org/wiki/D_(programming_language) seems to rather confirm this notion:
Though it does support things like in-line assembly and the like, I'm sure most C programmers would pass on it, as a C-alternative, based on those factoids.Walter Bright, the creator of D, is an active commenter here.
https://news.ycombinator.com/user?id=WalterBright
Zig is also worth mentioning, and pops up frequently.
Once, on a previous account, he actually replied to me. It's like a kid going to guitar center and the guy who replaces your strings is Axl Rose.
If you're on here, Walter, you're my hero. I also once interacted with Brendan Eich, who I admire as much for his role in web history as for his activism.
> his activism
Do you mean his homophobia?
D was never a C alternative, it was a C++ alternative.
^ and this person (no affiliation) has a much "truer" C alternative in the making, just for everyone's information: https://c3-lang.org/
Haven't gotten around to trying it out, but skimmed the documents a lot at one point. Always try to keep tabs on it, doesn't get the love it should.
Doesn't having a whole subset of the language called "Better C" qualify?
It was introduced in 2017, and not part of the original direction of D (it’s neither in 1.0 nor the 2.0 revision of the language)
That D exposes a curated subset of D doesn’t make it a C alternative, even though the ”betterC” aims to target people looking for a C alternative
> That D exposes a curated subset of D doesn’t make it a C alternative,
But why? You comment does not clarify what does this subset lack which prevents it being used as a C alternative. The intention is explicitly stated and the "spirit" argument is weak as overly subjective.
C is liked particularly, even considering all its shortcomings, for being a relatively limited language in scope, being raw but flexible.
D's scope seems to go far beyond what your average C programmer would want in a language; "use only 15% of the language and you'll be fine" (paraphrasing: "use only the 'better-C' subset", if that is what you meant, and it does seem to be a subset of D) seems a weird proposition; it still complicates things, as in collaboration, idiomatic feel and look of code, the amount of knowledge required to be competent in the language, complexity of a compiler implementation, portability of code etc... and by that logic you'd have to prefer C++ over C as well (since a lot of C is valid C++), or prefer C plus one safety feature added over C; but the "rawness"/limited scope/small size/procedural nature of C is what's appealing for many to begin with.
I for one think that a proper C replacement (C's strength also being the simplicity in which to implement a compiler for example, being the reason it's so ubiquitous in the embedded world) will be a much more limited proposition than D is.
Edit: And having been curious, even "Better-C" still has things many C-programmers wouldn't particularly like. Going by things listed here https://en.wikipedia.org/wiki/D_(programming_language)
Where to draw the line will be different person to person, but D doesn't seem to be a language "in the spirit of C", or a "modern version of it", at all.Viewing it as a C++ alternative makes much more sense. A `Better-C` "limit yourself to a subset of the language" compiler flag doesn't change that much.
> "Better-C" still has things many C-programmers wouldn't particularly like
I'd say a couple, not many.
> RAII
Who wouldn't like RAII?
> Metaprogramming
As a way to avoid preprocessor macros? Yes please.
> Nested functions
Already offered as extension.
> Member functions
I'm sure no C programmer would object to that.
> constructors, destructors
This yes. Agreed.
> operating overloading
Instead of _Generic()? Why not?
I wouldn't like RAII, and why I didn't add it to Odin. It's not a feature C programmers want. And you've just agreed that C don't want ctors/dtors, which is necessary for RAII to work... ctors/dtors are bad for their own reasons (mainly because you cannot handle error cases except through exceptions, which many people disable too).
Do you realize that D has betterC and now it also supports C compilation natively? [1] [2]
[1] D as a C Replacement (187 comments):
https://news.ycombinator.com/item?id=20323114
[2] Adding ANSI C11 C compiler to D so it can import and compile C files directly (105 comments):
https://news.ycombinator.com/item?id=27102584
Yes, I am quite aware. But it doesn’t make D any less a C++ alternative.
Safe to say that D is both C and C++ alternative, never say never.
If you aim to be both a C alternative and C++ alternative, in reality you are just a C++ alternative because you haven't understood why people prefer C over C++. Therefore D is a C++ alternative and that's what it was always trying to be, even with "BetterC".
Only if they aren't using anything beyond C99, because after that C is basically turning into C++ without Classes.
Most C programmers I know pretty much do that. I use C11 just for the atomics and that is it. And I know many C programmers who still use C89/C90 exclusively.
Depends on the point of view, especially those of us that think there is no reason for C other than legacy code, since C++ exists.
By the way, code that I wrote yesterday is legacy.
It certainly is, also known as D as C or Das C.
Odin seems to strike a really interesting balance between simplicity and practicality, especially for game development. I like the idea of having “batteries included” without too much abstraction getting in the way. For those who have used both Odin and Go, how do you feel about the differences in day-to-day development? Are there any features in Odin that you wish Go had, or vice versa? Would love to hear more real-world experiences!
I'd recommend going through https://odin-lang.org/docs/overview, as most of my points will be directly from there. Keep in mind it doesn't show _every_ feature (for instance, there are more built-in comptime procedures than shown https://odin-lang.org/docs/overview/#built-in-procedures-1), but does do a good job at displaying most.
Odin has all the features Go has (even struct tags https://odin-lang.org/docs/overview/#struct-field-tags), but adds:
- proper enums
- unions https://odin-lang.org/docs/overview/#unions
- built-in optional https://odin-lang.org/docs/overview/#maybet
- or_else/or_return/or_continue/or_break https://odin-lang.org/docs/overview/#or_else-expression (scroll down for the others)
- distinct types https://odin-lang.org/docs/overview/#distinct-types
- named arguments https://odin-lang.org/docs/overview/#named-arguments
- built-in matrix type https://odin-lang.org/docs/overview/#matrix-type
- built-in quaternions
- ternary operator, but you can use `bar := 1 if condition else 42` instead of ? and : if you'd like https://odin-lang.org/docs/overview/#ternary-operator
- default parameter values https://odin-lang.org/docs/overview/#default-values
- fantastic C integration
- forced in/exclusive range operators ..< and ..= https://odin-lang.org/docs/overview/#range-based-for-loop
- can get the zero value of any type using `{}` https://odin-lang.org/docs/overview/#zero-values
- defer if <condition> https://odin-lang.org/docs/overview/#defer-if
- explicit procedure overloading https://odin-lang.org/docs/overview/#explicit-procedure-over...
- bunch of vendored libraries https://pkg.odin-lang.org/vendor
- bit_set/bit_field https://odin-lang.org/docs/overview/#bit-sets https://odin-lang.org/docs/overview/#bit-fields
- proper slices (not the Go monster which combines a dynamic array along with slices) https://odin-lang.org/docs/overview/#slices
- `for x in xs` instead of `for _, x := range xs`, and `for &x in xs` if you want `x` to be addressable
- implicit selector expressions `.Member_Name` https://odin-lang.org/docs/overview/#implicit-selector-expre...
- parametric polymorphism with a ton of intrinsics https://odin-lang.org/docs/overview/#parametric-polymorphism
- - along with `where` clauses (similar to Rust) https://odin-lang.org/docs/overview/#where-clauses
Language cohesion has been _incredibly_ well thought out.
I mean, the biggest difference is that Go has a GC and Odin doesn't. And each's ecosystem reflects that... In practice they're simply not used for the same types of software.
I am currently limiting myself to 500 lines of (particle engine) code while listening to visual artists talking about their workflow in UE5 or Houdini, and Odin+Raylib are lovely to work in.
GingerBill has shouted out Go, but Odin doesn't particularly feel like a Go flavo(u)r.
To point out something that is a fail: I don't want to hear about how you simulated 10M particles on the GPU without acceleration forces.
Well at JangaFX, we can simulate a heck more than that on the GPU and you can apply as many complex forces applied to them as you'd like.
been playing around with odin and honestly the ease of getting started feels way better for me than most c-like stuff ever has. you ever think these smaller pain points keep more folks from switching than big technical features?
> This is the polar opposite of Zig’s embracing of metaprogramming for as much as possible.
I found this claim a bit strange. do people actually use metaprogramming in Zig a lot?
I haven't read the article yet, but this seems to conflate compile time evaluation with metaprogramming. Not all comptime evaluation is metaprogramming. I would argue the majority of comptime programming as it is used in Zig isn't even metaprogramming. Metaprogramming is a paradigm where there source or target data structure is primarily the language you're programming in. comptime evaluation of expressions that could be runtime evaluated is not that. I would argue that comptime evaluation of expressions that return comptime only values (like types) is not even inherently that.
Where you start to see actual metaprogramming in Zig is in functions like @typeInfo, @alignOf, @offsetOf, which actually let you operate on language constructs (ie: looping over the fields of a struct). This is not extremely out of the ordinary, but it's not done "as much as possible".
Another place that metaprogramming shows up in Zig is code generation using the build system. I've never done this, and I would argue this is usually recommended to be done as little as possible, rather than as often as possible.
Edit: I read the article, and while I think that the author was wrong about Zig pushing metaprogramming "as much as possible", they were fairly accurate in how it is used in the rest of the article, like for serialization. The thing is, most of my programs are not serialization. I use serialization as a means to do other things.
IMO it's one of Zig's advantages over C (text substitution macros are both too powerful and not powerful enough). If you're using Zig without metaprogramming, you're leaving a useful (if advanced) tool on the table.
C's preprocessor not being powerful enough is less a problem with text-substitution macros, more that they're not allowed to expand recursively which was an intentional design choice. There are some hacks you can do to get around it, and people have done cool things[1] within the limited space those hacks grant you, but there's a reason many C projects with extensive metaprogramming just use an external macro language (which is also just text-substitution).
IMO AST Macros are an even bigger problem than text substitution. Debugging metaprogramming of any kind past a certain point of complexity is a royal pain in the ass (even in a Lisp, Forth or Prolog), but AST explorers are next to useless for complicated logic problems that involve needle in a haystack searches of side effects. If you're dealing with a large AoS of heterogeneous SoAs which influence each other to shuffle around, and most of the related code and the structures themselves are generated via AST macros, you better be really comfortable with assembly analysis and debugger scripting.
[1] - https://github.com/Hirrolot/datatype99
Debugging complex Lisp metaprogramming is a piece of cake in the overall debugging landscape.
- It is not distributed across machines. No distributed fault tolerance issues.
- It doesn't run on a resource constrained embedded system, with poor visibility, but in your dev environment.
- It runs in a single thread; no flaky race conditions or deadlocks to debug.
- Its expansion-time performance rarely matters; and it is rarely bogged down with machine dependencies or other low-level stuff.
- It is unit-testable with cases does construct X expanding to construct Y.
I would rather debug a macro than any number of other things I've also debugged.
I can't comment about everyone, but I use it a lot for building libraries and such. I just recently built a database ORM, but since their metaprogramming is used for their generics I've run across it a lot just for those case.
Isn't all sorts of stuff metaprogramming in Zig? Generic types, vtable interfaces, printf. All use comptime to generate code.
i think "using comptime" as a definition of metaprogramming is not really accurate... for example, i think calling this metaprogramming is really stretching it:
i think calling "instantiating a generic type" meta-programming is weak, since you're not doing any of the metaprogramming yourself, though i would concede that if debugging is the concern there is a point there.same goes for "using std.debug.print"
Depends on the project, the general recommendation is to use metaprogramming like salt: just a pinch to add some flavor. Newcomers sometimes go bonkers with it though.
I like odin a lot, however, there are two things that just don't stick with me, and i ended up quitting:
- RTTI: just give me compile time type introspection and let me disable RTTI without making the language unusable
- when/import: just let me wrap an import inside a when block, being forced to split my file in 3 made me quit the language
Can't comment on RTTI, but lack of conditional imports are indeed an annoyance but I'm willing to put up with it because of all the other niceties in the language.
I remember times before Odin banned conditional imports. Those were different times, I miss them
There is compile time type introspection in Odin, it's just not that easy to use on purpose. But why do you not want RTTI? One of the reasons I wanted it over CTTI is because it's a fixed cost rather than an exponential cost—at both compile-time and run-time.
People who want CTTI is because they think it will produce better code because it is specialized for that type, and that is partially true, but also it will produce a hell of a lot more code. The canonical example of what I mean is the difference between doing something like `core:fmt` in Odin, which is a fixed cost at both compile-time and run-time, and then doing something closer to `std::format` in C++ (or other similar things in other languages) which will do a specialized procedure for each set of argument types. The former might be a huge initial cost if you only have a single type you want to print, but that cost is always the same regardless of many more types you add, it's also easier to debug. The latter is a small initial cost per type, and when the types get more and more complex, you also produce more and more code, which in turn increases the compiling time and binary/executable size.
As for the conditional imports, we did use to allow them but we found that what people were doing with them was kind of missing the point of the platform-specific features of the `package` system, and their code was always better if it actually utilized the package system correctly. There were some other quirks with the conditional imports which did confuse people because they didn't realize how things had to be executed (to allow for out-of-order type checking) and just disallowing it in the first place just solves that too (as a consequence, not as a goal).
You should be able to import everything, then use `when` to generate a unified constant name:
@(require) import "x_a"
@(require) import "x_b"
when ODIN_OS == .Windows { x :: x_a } else when ODIN_OS == .Linux { x :: x_b }
x.do_thing()
Related. Others?
Understanding the Odin Programming Language - https://news.ycombinator.com/item?id=42348655 - Dec 2024 (97 comments)
Moving my game project from C to the Odin language - https://news.ycombinator.com/item?id=42030704 - Nov 2024 (19 comments)
Golang developers should try Odin - https://news.ycombinator.com/item?id=41969839 - Oct 2024 (7 comments)
Marketing the Odin programming language is weird - https://news.ycombinator.com/item?id=41913319 - Oct 2024 (101 comments)
Odin isn't getting more features. The syntax is done - https://news.ycombinator.com/item?id=40873431 - July 2024 (3 comments)
Introduction to the Odin Programming Language - https://news.ycombinator.com/item?id=40688899 - June 2024 (60 comments)
Odin Programming Language - https://news.ycombinator.com/item?id=38836512 - Jan 2024 (102 comments)
Small joys of programming in Odin - https://news.ycombinator.com/item?id=36812175 - July 2023 (61 comments)
A Review of the Odin Programming Language - https://news.ycombinator.com/item?id=32799499 - Sept 2022 (140 comments)
I like Odin - https://news.ycombinator.com/item?id=32626543 - Aug 2022 (204 comments)
Odin Programming Language - https://news.ycombinator.com/item?id=30394000 - Feb 2022 (42 comments)
The Odin Programming Language - https://news.ycombinator.com/item?id=22199942 - Jan 2020 (141 comments)
The Odin Programming Language - https://news.ycombinator.com/item?id=20075638 - June 2019 (3 comments)
How does this compare with Zig or Beef?
Can someone explain how Odin achieves memory safety? Eg how does it avoid use-after-free?
It's not. However it is safer than C by default due to things like bounds-checking on arrays, slices (ptr+len), tagged unions, distinct typing for many things, an actual enum type, numerous checks for things like missing switch cases, and my more.
It's not trying to be memory safe, but rather try and catch many common mistakes that C does not catch easily.
As for use-after-free, I'd argue that is more of a problem with the memory allocation strategy in a language like C or Odin. And a change to something like an Arena like memory allocation strategy or something else reduces issues like that by a hell of a lot. `malloc`/`free` like approaches to memory allocation make use-after-free a lot more common because it making you micromanage allocations on a per-value level rather than on a per-shared-lifetime level. It's rare a single value has a unique lifetime, and I'd argue never in many projects.
One of the things I like about ObjC is that ARC is really really well done. The only time I care about memory management in ObjC is with cyclic references (eg: A->B and B->A). Those are about as rare as hen's teeth, and memgraph points them out if they ever do raise their head.
ObjC is pretty much the sweet spot for me in terms of language complexity and cognitive load over C, while providing so much more. It's really a shame that a lot of people (and I'm not pointing any fingers at anyone specifically) can't get past the [..] syntax, which comes from making ObjC a pure superset of C.
The language creator strongly suggests using arenas and zero-is-initialization. That's a programming paradigm that completely avoids having to keep track of zillions of small memory allocations, so the mechanisms needed to manage that are less important.
It does bounds checking for you but there's not memory safety feature a-la Rust. That's not the point of Odin anyway.
Yeah, it's not safety as an absolute term, more like "safer than C". Which, to be honest, anything with bounds checking is safer than C.
It doesn’t.
re Odin -- I do not like reusing important names in this way. Can I be the only one?
What do you mean exactly?
A C alternative means a language that will last for 50 years, whereas this seems more like "whatever's popular by way of LLVM". I can see some real smart stuff coming out of languages like Zig and Rust, where Odin seems just to follow along.
Seems needlessly harsh and also misplaced in some way. Zig is super non-ergonomic to any C-developer, and its explicitness at all costs is also non-C-like (meaning a rather big shift for someone actually liking C). Rust is a completely different beast altogether.
Odin is a rather simple, performant, pragmatic, procedural language, fixing especially things in C with regards to its type system and infrastructure (such as packages), adding niceties such as `defer` while being at it. I, as a C programmer, have it far higher up my list of languages to try than Zig or Rust by a rather large margin.
btw: "C alternative means a language that will last for 50 years" seems a snide that could be applied to any language less than 20 years old? I'm not sure what that's concretely meant to criticize here? Is Zig more a 50-year language than Odin, if so how? Odin is used for rather serious commercial products at JangaFX btw: https://jangafx.com/ and is quite beloved by some people using it.
I have long been aware of that particular user of Odin, after all the creators mention it frequently. The fact remains that the US government has warned against the use of languages such as Odin [1]. As such, it is competing in the extremely small niche of "languages best suited for embedded computing and operating systems". Suffice to say that most of its users likely do not use it for that. Finally there is the matter of trust. A while ago I was shopping around these new languages that have sprouted out of LLVM and watched a few talks from the creators of various languages. The Zig team were both ambitions and clear in their presentation. They gave me the impression of an experienced and motivated team. By contrast the Odin presentation I saw was utterly directionless and filled with fluff. I like to think I have a good nose for BS, and Odin trips it. That great wall of random corporate logos of companies which don't use Odin on their website doesn't help. Upon investigating, I find that the creator of the language is also a developer at JangaFX, so is either using the Odin website to advertise his own software, or hoping to obtain clout by mentioning large companies as if they used Odin when they do not. You might think I'm being overly critical, but I've learned the hard way to avoid things like this. It's a mighty pain depending on something which ends up abandoned or unused. The Zig compile supports multiple codegen backends, compiling C/C++ code, and easy cross-compilation. It is a considerable feat of engineering and shows a lot of dedication on the part of the creators. I can see nothing comparable on the Odin front.
Additionally, I don't think a C replacement should be immediately intuitive to someone who has only ever used C. To entice people away from on of the most popular and stable programming languages ever created, you must offer more than an incremental improvement. There needs to be a paradigm shift, which necessitates some degree of learning on the part of the developer.
[1] https://techtheworld.net/2024/03/06/the-nsa-list-of-memory-s...
Does Modula-2 count?
https://gcc.gnu.org/onlinedocs/gcc-15.1.0/gm2/
Or Ada,
https://gcc.gnu.org/onlinedocs/gcc-15.1.0/gnat_ugn
Maybe C++, given that the three main C compilers are written in it?
https://devblogs.microsoft.com/cppblog/the-great-c-runtime-c...
https://petereisentraut.blogspot.com/2013/05/moving-to-c.htm...
https://github.com/llvm/llvm-project/tree/main/clang/
I don't understand the point of this. When I say "Go flavour" I thought it would have lightweight threads like Go, but there is no mention of that in the description page. So it's another uninteresting curly brace language as far as I can tell. I'd rather use one with more traction.
"go flavour" refers to the similarity in the design philosophy, and some of the features. That said, it's still not Go.
For example, "errors as values" is a point that Odin makes, but it does make it in a slightly different light from Go. Whereas Go has an `error` type that encompasses all errors, Odin does not. Instead, it treats some types (booleans, enums, unions) as "special", in that they support things like `or_return`, which are typically your error propagation statements. Oh yeah, `or_return` is another big point, it does simplify a lot of `if err != nil { return err }` type of code.
And another big similarity to Go is the declaration syntax. It was inspired by one of Rob Pike's (iirc) comments on twitter about how they should have used a different syntax for Go instead.
From personal experience though, there are some things in Odin that I wish Go had. Its features play along together so nice, and it's so satisfying having three different language features come together in a nice logically-coherent simple way. That said, I don't think Odin is capable of replacing Go. Things like server-side logic and lightweight threads are probably where Go still excels at and beats Odin.
For systems-level programming I'd pick Odin though.
I just don't see the surface syntax as mattering that much. When I see "Go", I think lightweight threads, channels, and GC. Stuff like the declaration syntax is way down the list. Thanks though.