HNHacker News
TopNewBestAskShowJobs

gingerBill

916 karma · joined March 31, 2014

submissionscomments
gingerBill··on Odin Programming Language
Odin is a general purpose language, in the same way C.

Professionally, we use Odin to create all of our software at JangaFX: EmberGen, LiquiGen, and GeoGen.

Many people have been using Odin for similar purposes:

* game development

* application development

* 3D graphics

* physics related stuff

* etc

This is what a lot of people feel Odin's "niche" is, even if it is not restricted to that. A good example of this is Odin's first class features for array-programming, swizzling, matrices, quaternions, and many other things useful when dealing with 3D related things (graphics, physics, games, etc).

gingerBill··on Odin Programming Language
I highly recommend looking at:

* The Overview: <https://odin-lang.org/docs/overview/>

* examples/demo: <https://github.com/odin-lang/Odin/blob/master/examples/demo/...>

As for the first example: a basic lexing example is probably boring, but it does show some basic ideas of what the language is about. If people want to write better examples or just reorder the current ones, please feel free to make an issue or PR on the website's GitHub page: <https://github.com/odin-lang/odin-lang.org>.

gingerBill··on Odin Programming Language
Many languages don't aim for that. As it states on the front page:

> Odin is a general-purpose programming language with distinct typing built for high performance, modern systems and data-oriented programming.

> Odin is the C alternative for the Joy of Programming.

So if you have a problem that would have traditionally use C (or even C++), then Odin provides a more modern approach built for modern systems and higher control over low-level things such as memory, memory layout, memory access, and custom allocators.

gingerBill··on Odin Programming Language
> A way to generate bindings automatically from C Headers or even better - not having to generate bindings separately and just import C headers directly.

We do want to have an official bindings generator as part of the toolchain. There have been numerous third-party ones that people have created, but we need to have an official one now.

However, automatically importing C headers is not actually what virtually anyone wants in practice. Once you have imported the C header file, you pretty much want to:

* wrap the entire thing

* change the types to better reflect what things are (using Odin's richer type system)

* change names of things to better reflect usage and intent

* reorganize the declarations to better read things

* etc

There is also the second issue that C is technically TWO languages: the C programming language and the C preprocessor. People mix the two together and things cannot be easily translated. A good basic example of this is people using `#define` for constants, and thus that name has no semantic meaning in the language itself. A translator has to try and make some semantic meaning from the intersection of these two languages, even if people don't make a distinction when making APIs.

And Odin's `foreign` system allows [1] for a lot of really nice things that most other languages cannot do so tersely. Here are two examples of demonstrating bindings of C libraries that feel as if they were native Odin libraries WITHOUT any wrappers:

* https://github.com/floooh/sokol-odin/blob/main/sokol/gfx/gfx... (and the rest)

* https://pkg.odin-lang.org/vendor/sdl2/ and https://github.com/odin-lang/Odin/tree/master/vendor/sdl2

> Better tooling and standard library improvements.

Any concrete examples/ideas that you can give?

---

[1] https://odin-lang.org/docs/overview/#foreign-system

gingerBill··on Odin Programming Language
I am the creator of the Odin programming language, and thank you for the rhetorical insult :)

> procrastinated the important things that cause a language to really take off, in favor more trivial features.

So I should have focused on making a hype language rather than actually solve problems in programming that can be solved a the language level? I don't think anyone would call that "procrastination".

> At this point I think Odin has crossed into the territory of being wrong in the direction of too many features rather than too few. While having not delivered important tools that would cause the language to accrete an ecosystem.

That's vague as anything. Can you give any concrete examples?

> A must-have for wide adoption is a package/dependency manager.

And because Odin has a well defined concept of what a package is in the language itself, then creating one would be trivial for someone to do. Now this is going to be a VERY VERY controversial take but I do not want to __officially__ support a package manager. I know it's "so nice" to do something like `go get`, but I am not a huge fan of package managers in general and I honestly and truly believe that they have caused a huge amount of problems that cannot be solved by their existence. Please do not speculate what I "prefer", but I will not explain in this comment since it would take an entire article's/video's worth of explaining.

> while the sentiment in the Odin community is that the unnecessary concept of "collections" somehow solves the dependency problem.

This is just incorrect. There are few people who are working on a package manager for Odin, there is just not an OFFICIAL package manager.

And that is not what a library collection is for either. A library collection is a named search lookup. All imports are relative to either the current file OR a named library collection (a named directory). This solves the problem in C with `#include <...>` where you don't know how it is searching, whilst in Odin `import "core:fmt"` or `import gl "vendor:OpenGL"` or "import "../foo" has been made EXPLICIT where it is searching from.

----

I am not trying to create a "hype language" but actually make a language that solves mine and loads of people's actual problems. I do not view that as any form of procrastination whatsoever, and that you do is quite sad.

gingerBill··on Small joys of programming in Odin
Thank you for reading my articles and watching my videos!
gingerBill··on Small joys of programming in Odin
https://odin-lang.org/docs/faq/#what-have-been-the-major-inf...
gingerBill··on Small joys of programming in Odin
https://github.com/odin-lang/Odin/wiki/Odin-vs-Jai
gingerBill··on Ask HN: Programming without a build system?
Odin is a programming language without any silly complex build system, it is as simple as "odin build .", even for large projects.

Linking is done by describing it as part of the code with its `foreign` system [1][2]. The benefit of this approach is that your code itself describes what needs to be linked against what. It also has the benefit that if you don't use a foreign library, it doesn't get linked against due to its minimal dependency system.

If you want to see huge examples of this, I recommend checking out the vendor library collection[3].

n.b. I am the creator of Odin, and one of the original goals was to create a language that didn't necessitate a complex build system and just get to programming. Requiring a complex build system and package manager are anti-features in my opinion and make programming a worse experience to use. Odin borrows heavily from (in order of philosophy and impact): Pascal, C, Go, Oberon-2, Newsqueak, GLSL.[4]

Niklaus Wirth and Rob Pike have been the programming language design idols throughout this project.

[1] https://odin-lang.org/docs/overview/#foreign-system

[2] https://odin-lang.org/news/binding-to-c/

[3] https://github.com/odin-lang/Odin/tree/master/vendor

[4] https://odin-lang.org/docs/faq/#what-have-been-the-major-inf...

gingerBill··on A Review of the Odin Programming Language
Odin's shift behaviour is different to that of C's undefined behaviour.

To copy from the Overview[1]:

> The right operand in a shift expression must have an unsigned integer type or be an untyped constant representable by a typed unsigned integer.

and [2]:

> The shift operators shift the left operand by the shift count specified by the right operand, which must be non-negative. The shift operators implement arithmetic shifts if the left operand a signed integer and logical shifts if the it is an unsigned integer. There is not an upper limit on the shift count. Shifts behave as if the left operand is shifted `n` times by `1` for a shift count of `n`. Therefore, `x<<1` is the same as `x2` and `x>>1` is the same as `x/2` but truncated towards negative infinity.

In the case of overshift, the value is zeroed. Empirically I have found that the vast majority of shift factors can be known at compile time (or at least the valid range of integer), meaning it will compile to 1 instruction rather 2/3. In naïve C, the shift would look like this:

    (y < 8*sizeof(x)) > (x << y) : 0
In practice, the "select" instruction is never needed. This approach to shifting also places never in that it feels more like 2's complement in that `x << y` is now equivalent to `x (2*y)`.

This means that `(a << b) << c` is equivalent to `a << (b + c)`. In your example of `x << (32 - y)`, that logic works as what people intuitively intent it to mean, unlike in C where when `y` is 0, the shift behaviour is platform defined (nothing on x86 (5 bit shift) but zeros on powerpc (6 bit shift)).

[1] https://odin-lang.org/docs/overview/#arithmetic-operators

[2] https://odin-lang.org/docs/overview/#integer-operators

gingerBill··on A Review of the Odin Programming Language
You can apply that exact same logic to languages with RAII, e.g. C++. "It's not apparently looking at any snippet of C++ code which objects have constructors and destructors, without looking up each type and reading its documentation."

Note the difference here is between being implicit vs explicit, and obvious vs hidden. RAII is implicit and hidden, which may not be a good thing in certain projects, especially when copy constructors are being called all over the place. (And move semantics don't replace copy constructors in different places, only help reduce the use of them in many cases)

gingerBill··on A Review of the Odin Programming Language
My second quote above actually cover your cases in the case of "overshift". In the case of overshift, the value is zeroed. Empirically I have found that the vast majority of shift factors can be known at compile time (or at least the valid range of integer), meaning it will compile to 1 instruction rather 2/3.

In naïve C, the shift would look like this:

    (y < 8*sizeof(x)) > (x << y) : 0

In practice, the "select" instruction is never needed. This approach to shifting also places never in that it feels more like 2's complement in that `x << y` is now equivalent to `x * (2*y)`.
gingerBill··on A Review of the Odin Programming Language
Odin does not allow for negative shifts to begin with. To copy from the Overview[1]:

> The right operand in a shift expression must have an unsigned integer type or be an untyped constant representable by a typed unsigned integer.

and [2]:

> The shift operators shift the left operand by the shift count specified by the right operand, which must be non-negative. The shift operators implement arithmetic shifts if the left operand a signed integer and logical shifts if the it is an unsigned integer. There is not an upper limit on the shift count. Shifts behave as if the left operand is shifted `n` times by `1` for a shift count of `n`. Therefore, `x<<1` is the same as `x*2` and `x>>1` is the same as `x/2` but truncated towards negative infinity.

[1] https://odin-lang.org/docs/overview/#arithmetic-operators [2] https://odin-lang.org/docs/overview/#integer-operators

gingerBill··on A Review of the Odin Programming Language
The 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/valgr...

gingerBill··on A Review of the Odin Programming Language
Name a machine that people still program for that is NOT two's complement.

And the latest version of C now requires two's complement too!

gingerBill··on I like Odin
Do you honestly think Odin is "C with an extra 10%"? Or any of the decent alternatives that are available (e.g. Zig, Jai, etc)? Because if you really think that is the case, you know nothing about these languages nor have ever used them. All of these languages provide a hell of a lot more than "10%".

As for RAII, I do explain in another comments (https://news.ycombinator.com/item?id=32629951 & https://news.ycombinator.com/item?id=32631462) why RAII has alternatives and not necessary for every language. If you truly believe that RAII is necessary for you, then use a language that has it (e.g. C++, Rust, D).

gingerBill··on I like Odin
I've replied to you before on this in other comments. (here is one such example: https://news.ycombinator.com/item?id=32629951)

Odin has numerous memory safety features enabled by default. Having manual memory management does not entail no "memory safety". You could easily have a language with GC or ARC and still have all of the unsafe features of C. Objective-C is a brilliant example of this.

Many memory safety can be achieved with many constructs such as:

* Bounds checking for array-like types

* Having no pointer arithmetic

* Having distinct typing (virtually no implicit type conversions)

* Having no array-to-pointer demotion like in C (combination of the above to problems)

* Having actually decent array types: fixed-length arrays, slices, dynamic arrays, #soa arrays, etc

* Have length-bound strings rather NUL-terminated strings

* `Maybe(^T)` type to allow for non-nil pointers to be explicitly checked

* Built-in discriminated `union`s (of which `Maybe` is just one of those)

* Virtual Memory Protects

* And many more!

Most of the unsafe features in C/C++ come from most of the above features, especially pointer-semantics and the lack of a decent array type.

What Odin does not offer is ownership semantics and lifetime semantics, which is an entire discuss to itself which I won't talk in this comment.

gingerBill··on I like Odin
> You can just have your constructors not initialize your member variables. If they don't have default constructors that do work, then no work is done.

So your constructors don't do any construction?---defeating the entire point of a constructor.

> Yes, originally. Move-semantics are part of the language since C++11. Enough time has passed.

First, move-semantics solve a lot of the issues with copy-constructors in C++, as I previously stated. Secondly, what has time got to do with this? It's a solution in C++'s RAII with copy-constructors. Not the only possible solution but the one that the C++ committee settled on.

> I read and write C++ every day at work and in my free time and I rarely find this to be a problem. If I see a non-trivial type, I assume it's destructor is called at the end of scope. And whether I have to look up the destructor of some type or a corresponding free function (like in C code usually), makes no difference to me.

I'm also assuming that your code base uses constructors and destructors all over the place and is absolutely fine with the added costs of constructors and destructors. And that's fine. But they are implicit and when reading the code, you don't necessarily know if a constructor is being called from just reading it. That is just a statement of fact and not really a criticism.

> Gamedev can live entirely without exceptions and many other software projects do as well. You just have to write your constructors so that they do little work (which is encouraged anyways) and use methods to initialize them. Having static methods that return an optional<T> is also pretty common.

Firstly, is the argument here to make constructors only do trivial things in?---(which rarely ever happens in practice, especially if you use anything from the STL). Secondly, many game devs usually have have an explicit `init` method too for the exact reason you can separate allocation and initialization, and have the ability to handle failure cases with `init`, usually with a return value indicating this failure state. You can have static methods, yes, but then you are literally getting around the construct of an implicit constructor and having an EXPLICIT construction call.

RAII itself is actually very simple, but to make it useful is complicated and complex. The issue with RAII is not necessarily the scope-exit semantics but rather coupling this within the type system itself as a way to have scope-hierarchical-based management of resources.

gingerBill··on I like Odin
"Use after free" is a symptom of other problems. You can "solve" it by making it very different to do in the first place with something ownership semantics, but there are usually better ways of dealing with it in the first place.

One really good approach is to not use pointers in the first place and use handles. I highly recommend this post for more information: https://floooh.github.io/2018/06/17/handles-vs-pointers.html

Because use-after-free is a responsibility problem, handles are a way to make sure that a subsystem has responsibility over that memory directly rather than have it spread out across the program.

This is why Odin nor Zig "solve" this problem: solving it at the language level is not necessarily the best option.

gingerBill··on I like Odin
I recommend reading my reply to another comment regarding RAII: https://news.ycombinator.com/item?id=32629951

Also the article itself demonstrates different approaches to achieve behaviour similar to RAII through the `defer` statement and `deferred_*` attributes.

gingerBill··on I like Odin
"usually" by whom? "High control over memory" doesn't necessarily mean doing anything "unsafe" with it either. That term could allow for "unsafeness" yes, but it is not solely restricted to that. High control could just mean adding extra annotations about the access, or not having padding in a struct, or specifying the alignment, or many other things, none of which may be classed as "unsafe".
gingerBill··on I like Odin
It's slightly older than Limbo, and comes from Newsqueak. The difference is that Newsqueak used keywords for the other non-variable declarations. `x: int = 123`, `const X: int = 123`, `type My_Int: int`, etc.
gingerBill··on I like Odin
I never took it as a criticism, rather a clarification for others and to explain how Odin does things.

And it is indeed an interesting domain. Something to be very careful before making rash opinions on too. It is such an unexplored field so much potential!

gingerBill··on I like Odin
Odin has numerous concurrency primitives in the core library. And the synchronization primitives are based on a the modern construct of a `Futex`:

https://github.com/odin-lang/Odin/tree/master/core/sync https://github.com/odin-lang/Odin/tree/master/core/thread

We are planning on adding channels to the core library but we have not added them yet since there are quite a few different forms (SPSC, SPMC, MPSC, MPMC).

One thing that I would like to bring up is that Odin differs from Go in that it does not have `go`routines (green threads). These require automatic memory management and a huge runtime to make them possible. And you cannot easily add them after the fact to a language either without huge issues. Channels are very basic things but the thing that makes Go's concurrency powerful are the `go`routines, not the channels.

gingerBill··on I like Odin
There are a few reasons as to why there are different sized booleans in Odin.

One is dealing with foreign code. A lot of old C code used their own boolean type before it was standardized. And many people defaulted to typedeffing `int`. A good example of this is Win32's `BOOL` which is `int` sized, which would be backed by `b32` in Odin.

Another reason is that file formats may use different width booleans to a single byte.

Another reason is that things that are closer to the register-width are faster than byte-wide operations. So `b32` or `b64` even though it takes more memory up can be faster to deal with than `bool`/`b8`.

As for `bit_set`s in Odin, they are backed by integers and a brilliant solution to the problem of flags. They usually become a lot of people's favourite (but small) feature because of their ease of use and clarify of what they express.

gingerBill··on I like Odin
You are correct and Odin supports all of this.

`Maybe(^T)` exists in Odin.

Bounds checking is on by default for all array-like access. Odin has fixed-length arrays, slices, dynamic arrays, maps, and #soa arrays, all of which support bounds checking. Odin does not have pointer arithmetic nor implicit array-to-pointer demotion which is pretty much removes most of the unsafety that languages like C have.

Odin also has built-in support for custom allocators which allows you do a lot more with extra safety features too beyond the default allocator. Use-after-free is usually also a symptom of an underlying value responsibility and lifetime problem rather than a problem in itself, of which is fundamentally an architectural issue. Ownership semantics in a language in Rust does deal with this issue BUT it does come at a huge cost in terms of architecting the code itself to accommodate this specific way of programming.

There is a common assumption amongst many of the comments that if you have manual memory management, you are defaulting to memory unsafety. This is untrue and memory management and memory safety are kind of unrelated in the grand scheme of things. You could have C with GC/ARC and still have all of its memory unsafety semantics.

gingerBill··on I like Odin
Regarding Odin and Hare, I'd argue most people would easily be able to tell them apart from the syntax alone because the declaration syntaxes are quite different. And most people judge a syntax pretty much solely by the declaration syntax itself.

Regarding RAII, I explain in another comment (https://news.ycombinator.com/item?id=32629951) the issues with RAII and what it requires to be useful. Odin has the similar rule of "no allocation without an allocator" but has the implicit `context` system which passes the current context's allocators around. Odin also has core library support for valgrind, callgrind, memcheck, and soon helgrind.

Odin has features (which this article does showcase) which are akin to RAII but are not attached to the type system. And as I explained in the previous comment, RAII wouldn't even make much sense in Odin (or Zig for that matter) and would probably never a good idea to add it later. There are better alternatives to RAII for languages such as Odin and Zig.

gingerBill··on I like Odin
Thank you for that. I rarely use HackerNews and I was just trying to clarify my own position.
gingerBill··on I like Odin
To quote the FAQ (https://odin-lang.org/docs/faq/#is-the-odin-compiler-self-ho...):

> Odin is not currently self hosted nor will be until after version 1.0 when the main implementation of the Odin compiler adheres to a specification and is heavily tested. In general, self hosting before a stable language and compiler exists is masturbatory pleasure.

gingerBill··on I like Odin
I'm not against self-hosting.

To quote the FAQ (https://odin-lang.org/docs/faq/#is-the-odin-compiler-self-ho...):

> Odin is not currently self hosted nor will be until after version 1.0 when the main implementation of the Odin compiler adheres to a specification and is heavily tested. In general, self hosting before a stable language and compiler exists is masturbatory pleasure.

← PreviousPage 6 of 9Next →