31 ms·
A Review of the Odin Programming Language
- gnuvince 4y agoOdin and Zig are the two up-and-coming languages that I keep my eye on. I like how they are trying to find a sweet spot where they offer more than plain old C, but without becoming overbearing like Ada, C++, or Rust.
- bsaul 4y agoI’m really surprised to see those language emerge after having read so many praise about rust being a fantastic system language. Although, from a personal standpoint, anytime i see rust code or read about horror stories fighting the compiler i wonder how that language gained so much popularity.
- lucasyvas 4y agoIt's popular because the compiler is difficult - people would rather suffer the pain at compile time instead of runtime for particular projects, so it is very well suited to those.
- doliveira 4y agoI still feel that we're overdue for some paradigm shift in programming languages. There's a nebulous feeling, probably informed by my amateurishness, that some tasks just shouldn't be this hard. Seeing the whole buzz around GitHub Copilot, which seems to confirm that 90% of the typing we do is useless, makes me think that there's another level of "semantic abstraction" (?) we're missing.
- taylorius 4y agoAn interesting point. I wonder if the knowledge contained in github copilot could somehow be extracted to come up with suitable semantic abstractions.
- zasdffaa 4y agoVery interesting. I don't have experience with copilot, but with my own programming I tend to abstract heavily until repetition is removed and there's little to repeat (that said there are places where the language, C# in my case, could support my style of programming better). I'll check out some vids.
- afranchuk 4y agoI think an interesting distinction is this: it's not that 90% of the typing you do is necessarily useless, it's that it's been done before. Copilot is, in a sense, drawing from a corpus of prior work. In that way you are kind of using it as if you found a published library for your more specific use cases. So it's allowing you to draw on prior work without necessarily having external packages split up with the granularity of many variations of functions (which, ideally, would allow you to pull in exactly what you need from prior work, but would certainly be onerous in practice). That being said, I've never used Copilot myself, so I can't speak very confidently about it. But from what I've seen, it kind of allows you to incorporate every library that's ever been made open source into your project, but in a more granular fashion. Which naturally would save you some typing :) P.S. I realize Copilot isn't necessarily copying other code verbatim, though I assume pretty often it basically ends up doing that, at least in pieces.
- crdrost 4y agoThis is an interesting take. One does need to draw a distinction between “what everybody writes” (copilot generates) and “what has to be written” (this code is the ‘useless’ stuff bemoaned by the parent comment). Obviously everybody writes what has to be written, but you're right that there is a distinction. One gets a vision of the copilot autocomplete, as kind of missing what would be an essential highlight, in the templates it provides. “These parts highlighted in red, do not change those, for some reason everybody does it that way. But these parts highlighted in yellow, I've seen a bunch of different takes on those; this is where some variation occurs and where you might want to customize it yourself.” On this take, copilot is a poor way of providing syntactic templates—macros—and indeed those macros take the form of template substitution, which means they form in theory a lambda calculus for that metalanguage. That is itself interesting because I only know of one programming language which says “we are going to live out here in la-la-functional-programming-math-land, but we are going to describe values which are actual fragments of computer programs,” and that language is Haskell—though never used to write at this scale!. Interesting to think that the Ur-goal of Copilot is to provide what you were missing because you didn't wrap your language in Haskell in the first place! With that said, a better way to start with metalanguage design if this problem irks you is probably not Haskell itself (it doesn't have an easy way to swap out its compile target language from C-- to some other target, I don't think) but something like Ometa2: http://wiki.squeak.org/squeak/3930 http://wiki.squeak.org/squeak/3930
- bsaul 4y agoa programming language (together with its standard library) should guide you toward safe code, while keeping an enjoyable experience. Saying "this thing is hard to get right, so the PL should make you feel the pain" is only marginally better than a language that pretends the problem isn't there at all.
- macintux 4y agoI feel like some languages make it much easier (or at least require less code) to accomplish certain tasks (Perl, for text processing, and Erlang for concurrency/distributed systems), while other languages make it more practical to do anything at all, but the tradeoff is that they’re much more verbose. Kitchen sink languages require you to build the kitchen before you can cook.
- bsaul 4y agothere's good difficult, the one that forces you to clarify your point, and there's bad one: the one that makes simple constructs hard or impossible without going through hoops. From my understanding, rust has a little bit of both.
- hsn915 4y agoOdin emerged partly out of the "Handmade Network" which is a group of people interested in a style of programming that is very different from what is usually accepted by the rest of the industry as best practice. See: https://www.youtube.com/watch?v=f4ioc8-lDc0&t=4407s https://www.youtube.com/watch?v=f4ioc8-lDc0&t=4407s
- kaba0 4y agoWhat I genuinely don’t understand is why do we focus so much on the low-level/system front? It is (or very much should be) a small niche, and most business applications are better served by managed languages that won’t get a huge list of vulnerabilities from memory corruption alone.
- lostdog 4y agoLow-level and system programming are the areas most hurting for better languages. High level has several modern scripting languages (Python, Ruby, Javascript), and typed languages (Java, C#, Kotlin). Low-level programming has had C and C++ for 30+ years, and both have major problems that need fixing. Plus, there's lots of interest in having programs run much much faster, especially as people realize that every line of Python they write could be 10x faster in a lower level language, with minimal extra work. This is why Rust, and now Odin, get so much attention. Of course, there's also a renaissance brewing for mid-level languages, including Go, nim, and crystal.
- Hemospectrum 4y agoSystems-level programming is a frontier for language design precisely because higher-level domains are already so well-served by established platforms. If your problem can be solved in Python or JavaScript, you're potentially creating a lot of work for yourself by using a language that's sort of like either of these, but not actually compatible with their libraries. The internet is littered with upstart languages that were made this way and withered on the vine. On the other hand, if you're working in a problem space with tighter performance constraints, and you already can't touch these languages, and you can't even count on libraries written in C or C++, then you suddenly, paradoxically, have a lot more options.
- shpongled 4y agoPersonally, I would use Rust even if it was managed/not as low level. Advanced ML type system + best-in-class developer UX/tooling is the biggest selling point for me.
- Existenceblinks 4y agoIt combines two things that appeal two large camps of developers, ML style and performance. I even think that its memory safety isn't that the main attractive point. It's like a language that's aim to sell both ML family and C guys, and that's over 50% of volume of devs' voice.
- Tozen 4y ago> ...i wonder how that language gained so much popularity. Well, we should not underestimate the power of corporate backers pushing and hyping their languages. And once the hype picks up momentum, it takes a lot to slow it down.
- jessermeyer 4y agoOdin has renewed my joy of programming. Built in bounds checking, slices, distinct typing, no undefined behavior, consistent semantics between optimization modes, minimal implicit type conversions, context system and the standard library tracking allocator combine together to eliminate the majority of memory bugs I found use for sanitizers in C/C++. Now I'm back to logic bugs, which neither Rust nor sanitizers can help you directly with anyway because they rely on program and not language semantics. Obviously these features together do not eliminate those classes of bugs, like Rust, but Odin chooses a different point on the efficient frontier to target, and does so masterfully. To put the cherry on top, the sane package system, buttery smooth syntax, sensible preprocessor (the 'constant system'), generics, LLVM backend for debug info / optimization, open source standard library, simply build system, engaging and well intended community make day to day programming a pleasant experience.
- hsn915 4y agoOdin's stance towards undefined behavior was probably the decisive element that made me prefer it over the other languages. https://twitter.com/TheGingerBill/status/1495004577531367425 https://twitter.com/TheGingerBill/status/1495004577531367425
- raphlinus 4y agoHow does this work in practice? Is the behavior of a use-after-free defined? Data races? The latter even more so for objects that don't fit in one machine word, such as slices. While avoiding undefined behavior is a noble goal, my personal feeling is that actually achieving that will be much harder than it might first seem, and will probably end up precluding a good deal of optimization. Of course, C has an entire class of UB that is much more excessive than useful, for example left shift of a negative integer. It's clearly and obviously possible to do much better than C. I'm just skeptical that "no UB at all" is in reach for a low-level, systems programming language that is also portable and can be compiled with optimization comparable to C.
- hsn915 4y ago
- tialaramex 4y agoYou might want to also pay attention to Jai (or whatever Jonathan Blow ends up naming it) Like the author of Odin, Blow has significant experience writing software in a specific domain (video games), has strong opinions about what's wrong with existing languages, and decided he could do better. You can't actually use Jai yourself yet, it is as yet a closed beta (though you might know somebody who can get you in), but you can already get a flavour of it and I think it's probably in the sphere of things you'd be interested in judging from your comment. Personally I think we need to stop treating safety as optional, as a C programmer for about 30 years, about 15-20 years of that for pay, I found Rust very pleasant and would now always choose it over C or these C replacements - although currently I get paid to write Python and C# in my day job. But I'm clearly in the minority, for now at least, so I expect at least one of these C replacements like Odin or Zig to get significant adoption. Probably pays to know several of them, as it's far from clear which will succeed and I doubt there's room for all of them over the long term.
- adamrezich 4y ago> You can't actually use Jai yourself yet, it is as yet a closed beta (though you might know somebody who can get you in) you can always try asking, worked for me
- Tozen 4y agoBut, what are people going to do with Jai, that they can't already do with Odin? As Odin was strongly influenced by Jai, it could be argued that most of whatever was innovative, is already incorporated in Odin and available today. Even more, since Odin is publicly available, its arguably being "battle tested" to a higher degree to make it a more polished product. From my understanding, Jai is still years away from a general public release.
- verdagon 4y agoOne thing I like about Odin is that you can use any allocator with any existing function, without wiring that function to specifically do that. It just comes for free. In a way, it completely decouples the code from the allocator choice. It's especially nice because we can use any allocator with any third party code. I think this kind of decoupling is a big step in the right direction. The more concerns we can decouple from each other, the simpler and more flexible our codebases become and the less time we have to spend infectiously refactoring.
- tialaramex 4y ago> It just comes for free To be fair, specifically the price is a hidden context passed to every function. Hiding it means the programmer needn't expend effort thinking about it as they would if you did this by hand, but in performance terms this isn't really free.
- astrange 4y agoThis can be implemented many different ways without losing a register (/ other parameter storage). It’s called dynamic scoping or thread local variables.
- _0w8t 4y agoThread-local variables are implemented using a reserved register. Essentially thread-locals in C++ are the hidden context.
- astrange 4y agoThat doesn't "lose" a register because the program already wasn't using it.
- LegionMammal978 4y agoTo be fair, they're implemented with one of the segment registers, at least on x86-64. So there isn't much else that programs could have used it for, since it takes a syscall just to set the value.
- michaelwww 4y agoI was wondering why the author would think me, the reader, might get very angry about something he wrote, but then I saw this from the creator of Zig: I see a lot of toxic Rust vs Zig discourse on Twitter right now... https://twitter.com/andy_kelley/status/1568679389113757698 https://twitter.com/andy_kelley/status/1568679389113757698 There seem to be a lot of heated passions about C replacement languages right now. The Zig v Rust issue seems to boil down to the Rust community putting a lot of effort into making memory safety a priority for everyone in the industry and don't think new languages should backslide into C's "unsaftey"
- bigbillheck 4y agoIt wasn't helped by Ziglang's VP of Community Loris Cro using the term 'full-time safety coomer'.
- wchar_t 4y agoHe apologized: https://twitter.com/croloris/status/1568704125826748416 https://twitter.com/croloris/status/1568704125826748416
- cyber_kinetist 4y agoI think the problem was after he apologized, he should have just stayed quiet online for a few days (for Twitter to let some steam off) but failed to do so. Maybe it's a bit hard for someone who has a very "online" job to be offline for some time. (Vice President... of Community? Is this an official job title related to the Zig Software Foundation?)
- LAC-Tech 4y agoCome on, that was funny.
- turminal 4y ago> the Rust community putting a lot of effort into making memory safety a priority for everyone in the industry It would help if they did that in a manner that resembled harrassment a bit less. I realize most of the community means well but by now it should really be clear that they picked the wrong way.
- agluszak 4y ago> Odin has two idiomatic ways to allocate memory. The make and new procedures. When destroying something created with make you call delete. When destroying something created with new you call free. This is a bit confusing if you come from C++ where new is paired with delete. What's the difference between the make and new then? > There’s no need for a build system, nor to explicitly call the linker. The compiler does it all. Umm, so there is a build system, but it's just integrated into the compiler? What is the benefit here? Rust has an excellent build system out of the box (cargo), but it's still separate from the compiler itself.
- hsn915 4y agoThe distinction between make and new is similar to Go. new allocates memory for the given type. make allocates memory referenced by the type. For example, a slice is defined as: slice :: struct { data: rawptr, length: int } When you make a slice, you don't allocate space for the struct. You allocate space for the data to be referenced by the struct. > Umm, so there is a build system, but it's just integrated into the compiler? What is the benefit here? Rust has an excellent build system out of the box (cargo), but it's still separate from the compiler itself. What's the benefit of not having the build system integrated into the compiler? Ideally if you are not linking to external libraries, and all the code is in the language, you don't want to go through the typical stages of the C compiler where it first produces object files and then links them. You want to just produce the final exe directly. I don't think Odin does this - at least at this point - but anyway messing around with object files should be considered obsolete.
- agluszak 4y ago> What's the benefit of not having the build system integrated into the compiler? Being able to write new/integrate with existing build systems (i.e. Bazel). > Ideally if you are not linking to external libraries I'm afraid that's rarely the case. > messing around with object files should be considered obsolete. Messing with them yourself, as you need to do when you use `make` in C/C++ (without cmake or anything more fancy) - I agree, it should be considered obsolete. But what if I want to mess with them because, for example, I want to add support for Odin to Bazel?
- dikaio 4y agoThe way the article reads feels very authentic and the transparency in conflict of the review is refreshing.
- d_burfoot 4y agoI decided that if I ever get a dog, I will name him Odin. That way, when he gets lost, I can walk around and yell "Ooooodddddiiiiinnnnnn!!"
- dang 4y agoRelated: Odin Programming Language - https://news.ycombinator.com/item?id=30394000 https://news.ycombinator.com/item?id=30394000 - Feb 2022 (42 comments) The Odin Programming Language - https://news.ycombinator.com/item?id=22199942 https://news.ycombinator.com/item?id=22199942 - Jan 2020 (141 comments) The Odin Programming Language - https://news.ycombinator.com/item?id=20075638 https://news.ycombinator.com/item?id=20075638 - June 2019 (3 comments)
- michannne 4y ago> This means valgrind cannot really detect memory issues as well since Odin has it’s own internal allocators. helgrind cannot work because Odin doesn’t use pthread primitives. ltrace cannot work because that just provides wrappers over every libc function, etc Unfortunately, I've gone through too many bugs that had to be fixed through valgrind debugging that I'm unwilling to part with it
- gingerBill 4y agoThe Odin team are working to put valgrind, helgrind, callgrind, memcheck, etc in to the Odin core library to provide better debugging tools! Along with many other debugging tools. https://github.com/odin-lang/Odin/tree/master/core/sys/valgrind https://github.com/odin-lang/Odin/tree/master/core/sys/valgr...
- torstenvl 4y ago> defer: Declarative control flow that obviates the need for RAII. I feel like RAII is a term that has expanded to mean more than it means on its face. Maybe someone more familiar with the larger meaning of the term could help me understand? How does a defer capability have anything to do with initializing a resource upon allocation?
- Rusky 4y agoIt's had those extra connotations from the start- the whole reason to tie allocation to initialization is so that you can also tie deallocation to destruction, making it automatic and thus less error-prone. "RAII" is mostly just a confusing name for "destructors."
- syrrim 4y agoIn C you have a system of memory allocation tied to scoping. A statement like "int x[10];" allocates memory such that when x goes out of scope, the memory is deallocated. RAII generalizes the concept so that when the variable comes in scope, some initializer function is called, and when it goes out of scope some destructor is called. This allows us to use it for dynamic arrays (unlike VLAs in C), hash tables, etc. We can replicate the system by simply calling the initializer when the var comes in scope, and the destructor when it goes out of scope. However, this creates the problem that the two statements are far apart from one another, and thus there is a chance that they might grow out of sync as the code changes. Defer allows us to cause some action to occur when the variable goes out of scope, but declare this at the site where we perform initialization, thus grouping the two together and making it easier to modify them in tandem.
- pie_flavor 4y agoAs with most C++ terms, it means something completely perpendicular to what it implies. In general it means that deterministic destructors release a resource at the moment the value representing it goes out of scope, e.g. deallocating memory or closing a file handle. IMO Odin is very wrong on this point: the important thing about destructors is that you know where to find them, so e.g. you can have closures that know how to free their captures when they are freed. There's nothing like that for Odin.
- tayistay 4y ago> I don’t buy into the rhetoric that memory safety solves everything I haven’t heard that rhetoric, only that memory safety is a really good thing. If I can pay up front with some static analysis and eliminate entire classes of bugs, that’s just such a great thing, even if it doesn’t solve everything. I want to like and use Odin, because the guy behind it seems really cool, and it’s pretty indie, like zig. But the strong guarantees of rust are just so compelling.
- Ygg2 4y agoMemory safety is a bit like seatbelts (pardon the analogy). It's possible to drive a car and never need it and seatbelts can be uncomfortable. But I would never want to get in a car without one and it makes me question the sanity of people with saying stuff like "You most likely won't need it".
- discreteevent 4y agoThere are plenty of programs written in C that will not kill somebody if there is a memory safety issue. It is not "insane" to write a game in C. Seatbelts are about physical safety which is in a completely different category.
- Ygg2 4y ago> There are plenty of programs written in C that will not kill No, of course not (see analogy) - It will just make me wish for sweet, sweet release of death (see hyperbole). Point is, you can eliminate a class of nasty bugs. And instead you double down on it. So, I'll use a more programming example. C has more foot guns than just memory issues e.g. `if (a=4)`. For all its faults, Java only allowing boolean expression in if statements was a move in right direction. Now imagine after Java some C inheritor (Rust, Go, Carbon, Zig, Nim...) looked at `if (a=4)` and said. Yes. We need that in our lang. Can't you see we regressed in this hypothetical example? We traded correctness for expressivity. Same with memory safety. Rather than using a GC or some borrow checking system, we shrug and say, well what can ya do?
- kapilkchaurasia 4y ago