HNHacker News
TopNewBestAskShowJobs

gingerBill

916 karma · joined March 31, 2014

submissionscomments
gingerBill··on Choosing a language based on its syntax?
> I never got why compilers don't have pluggable syntaxes.

Because then you've created dialects and produced the Curse of Common Lisp all over again.

Syntax matters a heck of a lot, and you want consistency and coherency across codebases of the same language, otherwise you don't have a language at all. So wanting it "pluggable" is in fact the worse possible choice you want.

It's also a naïve view to think that concrete syntax can be trivially swapped out with the abstract syntax remaining. For certain things it can usually work (like declaration syntax in the article) but for most things it cannot.

gingerBill··on Choosing a language based on its syntax?
Yes it does. You can even type `;` anywhere too, go an try it.

Because of how good the rules are for Python's needs, most people never know that semicolons even exist in Python.

gingerBill··on Choosing a language based on its syntax?
Did you even read the article, even the heading of that section? You know there is a huge majority that do not want semicolons whatsoever, so saying people should just suck it up is actually a determent to the adoption of the language because of people's general tastes.
gingerBill··on Choosing a language based on its syntax?
That sidestepping only introduces significant whitespace, which may not be what people want in the first place. It can be quite common to align call expressions by the parentheses if they span multiple lines for clarity, and you preventing might not be desireable.
gingerBill··on Choosing a language based on its syntax?
The article does no such thing and just focused on declaration syntaxes and semicolons. I can class literally any language into the three categories for declaring variables.

* Haskells are name-focused languages. * Smalltalk is a name-focused language. * LISPs are qualifier-focused languages.

I think you might have a blinkered viewpoint in how you have interpreted the article.

gingerBill··on Choosing a language based on its syntax?
Those syntax examples are literally just general examples, not the only way you have to write them. But to categorize the ones you wrote:

* Clojure is qualifier-focused * Prolog is name-focused * Forth is qualifier-focused (`:` is the qualifier in this case)

gingerBill··on Choosing a language based on its syntax?
I literally had to write an extra article because of the number of people who thought I was saying syntax doesn't matter. It matters a hell of a lot:

https://www.gingerbill.org/article/2026/02/21/does-syntax-ma...

I was trying to be as clear as I possibly could within that article to state I was only focusing on those two specific topics, rather syntax as a whole. How people judge a language based purely on its declaration syntax and nothing else. Where the declaration syntax makes the least difference compared to the rest of the syntax in the language. And still people wrongly interpreted the article.

gingerBill··on Mitigating the Billion Dollar Mistake
In the first case in a language with type inference, I'd argue it would probably be written a bit different. And probably something like the following two cases:

    x := &bar
    if is_foo { x = &foo }
    // or
    x := &foo if is_foo else &bar
I know this is a simple example, but it's kind just a different way to think about the problem. Sometimes the default C way of having to specify the type first is a good enough of a nudge away to not do when you can just infer the type from the expression. Especially when this variable is being used not as a variable in itself but as an alias for another. The place where it is more likely to have a `nil` pointer due to no explicit initialization in Odin would be within a struct, rather than on its own on the stack.

In the second case, Odin's approach would probably just not even do that, but rather `f, b := grab_data()`. The use of `&` is when it needs to be an in-out parameter (i.e. read and write to), which means it has different functionality.

gingerBill··on Was It a Billion Dollar Mistake?
The thing that is at odds with Rust is the second part of the article: the difference in mindsets.

Rust by default doesn't really encourage the group-element mindset and people have to work against the language in order to do it. And what usually happens is people work around the borrow-check as a result, through the use of a handle system. And they do this in order to get the lifetime benefits, performance benefits, and also get around the problems of the ownership semantics.

Of course you can do this in Rust, but the point is that the default approach in Rust does not encourage it at all. The default Rust mindset is the individual-element mindset.

gingerBill··on Was It a Billion Dollar Mistake?
To make `Maybe(T)` feel like a multiple return, you just need to do `.?` so `maybe_foo.? or_return` would just the same.

But as you say, it is more common to do the multiple return value thing in Odin and not need `Maybe` for a return values at all. Maybe is more common for input parameters or annotating foreign code, as you have probably noticed.

gingerBill··on Was It a Billion Dollar Mistake?
The first paragraph from the article:

> *TL;DR* null pointer dereferences are empirically the easiest class of invalid memory addresses to catch at runtime, and are the least common kind of invalid memory addresses that happen in memory unsafe languages. The trivial solutions to remove the “problem” null pointers have numerous trade-offs which are not obvious, and the cause of why people think it is a “problem” comes from a specific kind of individual-element mindset.

gingerBill··on Odin: Moving Towards a New "core:OS"
Unfortunately I don't think you've understand what I was I trying to say.

Rust was designed from day-0 around explicit individual-value based initialization. Odin from day-0 was not designed around this (explicitly).

This ever so minor choice might not seem like a big thing to you, as you have stated in your comment, but it leads to MASSIVE architectural decisions later on when the user programs.

Odin could not "just add" non-nil pointers and it be "fine". It would actually not be Odin any more, and the entire language would not even be a C alternative any more, and feel much more like C++ or Rust. Rust and OCaml (which Rust is based off) are different kinds of languages to Odin and their approach does not translate well to what Odin (or C) is trying to do.

Unfortunately I will not be able to explain this to you in a comment or article, and it is something that takes a while to understand since it is a subtle effect of locality affecting globality. The best video on this might be from Casey Muratori: https://www.youtube.com/watch?v=xt1KNDmOYqA

> Yes, initialization can be less efficient in Rust but then most of the time spent is spend in algorithms when they run, not during initialization of the data structure.

Sadly this isn't as true as you think it is. I've written a lot of C++ code before and doing its boilerplate for ctors/dtors actually leads to much slower code in general, and I'd argue this does apply to Rust too. Most of the time isn't necessarily spent in "algorithms", especially when "algorithms" also include initialization of values. You've turned something which could be O(1) into at best O(N), which does not help when things scale, especially with "algorithms".

gingerBill··on Odin: Moving Towards a New "core:OS"
Here's my reply to him so I don't have to repeat it all: https://news.ycombinator.com/item?id=46457272

But in short, my hypothesis is because the Odin compiler bundles many graphics-related packages but does not bundle with an official http package, it is therefore "only" for games. He has no idea what games actually involve to make, and it is the most accidental compliment he could give. And we already have an FAQ answer for this: https://odin-lang.org/docs/faq/#is-odin-just-a-language-for-...

gingerBill··on Odin: Moving Towards a New "core:OS"
Thank you for the comment and trying out Odin, but there are a few things in your comment which seem a bit off to me. Odin is trying to be C alternative, not a Go without GC.

Odin does share a lot of similarities to Go, even including it's distinct type system. So requiring more type casting than your Go code is actually a surprise to me because Odin's rules a little more lax than Go's, but it's probably because you don't cast as often in Go for whatever reason, probably because it's not actually a systems-programming language, it's mostly just for web stuff. You're not actually dealing with different sized integers and floats all the time, you're just using `int` and `float64` in Go. If you had to use more, you'd actually realize Go requires even more casts than Odin.

Odin does lack methods BY DESIGN. It is not a design flaw, like you are thinking it is. And adding methods is not a "no-brainer", or you could argue adding them is a "no-brainer" as in you are not thinking about the consequences of them. We have a FAQ section on this topic entirely, so I won't copy and paste it here: https://odin-lang.org/docs/faq/#but-really-why-does-odin-not...

As for the other stuff you are complaining about: they're just libraries...

Odin is going to get an _official_ http package soon, and it has been in the works for a long time. It's going to be based on the native kernel async APIs (IOCP, io_uring, KQueue, etc), and from our preliminary tests, is a heck of a lot faster than any of approaches done with Go (and even many of the Rust approaches too).

There is a reason that I "vehemently [refuse] this notion and [try] to fight in every podcast" that Odin is only for games. You're literally saying because the official Odin compiler lacks a single official library (`core:net/http` which is in works as I said) for dealing with http, it isn't for web dev? Are you actually serious? There are third party libraries that already do this, but as I said, we are working on an official one already, which will be coming out this year for definite.

I highly recommend reading the following FAQ question to regarding the entirety of 'Is Odin "just" a language for game development?": https://odin-lang.org/docs/faq/#is-odin-just-a-language-for-...

But saying it is for gamedev is the most accidental compliment you could give it be gamedev is pretty much the most wide domain possible where you will do virtually every area of programming possible. All your comment told me is that you have no idea what gamedev actually involves.

gingerBill··on Odin: Moving Towards a New "core:OS"
Here's what I said in another reply: https://news.ycombinator.com/item?id=46454185

But to answer your general points here: Odin is a different language with a different way of doing things compared to others, so their "solutions" to specific "problems" do not usually apply to a language like Odin.

The problem with solving the "60% case" means you now have introduced a completely different way of programming, which might solve that, but the expense of so many other cases. It's a hard language design question and people focusing on this specific case have not really considered how it effects anything else. Sadly, language features and constructs are rarely isolated from other things, even the architecture of the code the programmer writes.

As for C code, I agree it's bad that there is no way to know if a pointer uses NULL to indicate something or not, but that's pretty much not a problem in Odin. If people want to explicitly state that, they either use multiple return values, which is much more common in Odin (which is akin to Result<&T, E> in Rust, but of course not the same for numerous reasons), or they use `Maybe(^T)` (akin to Option<&T> in Rust).

I understand the problems that C programmers face, I am one, which is why I've tried to fix a lot of them without trying to be far from the general C "vibe".

gingerBill··on Odin: Moving Towards a New "core:OS"
Odin's type system is just different to many other languages, and trying to compare it to others doesn't always work out very well.

`Maybe` does exist in Odin. So if you want a `nil` string either use `Maybe(string)` or `cstring` (which has both `nil` (since it is a pointer) and `""` which is the empty string, a non-nil pointer). Also, Odin doesn't have "interface"s since it's a strictly imperative procedural language.

As for you question about base values, I am not sure what you mean by this. Odin hasn't got a "everything is a pointer internally" approach like many GC'd languages. Odin follows in the C tradition, so the "base value" is just whatever the type is.

gingerBill··on Odin: Moving Towards a New "core:OS"
n.b. Sorry for the long reply, this is actually a really complex and complicated topic in terms of language design, trade-offs, and empirics.

It's a trade-off in design which is not immediately obvious. If you want to make pointers not have a `nil` state by default, this requires one of two possibilities: requiring the programmer to test every pointer on use, or assume pointers cannot be `nil`. The former is really annoying, and the latter requires something which I did not want to (which you will most likely not agree with just because it doesn't _seem_ like a bad thing from the start): explicit initialization of every value everywhere.

The first option is solved with `Maybe(^T)` in Odin, and that's fine. It's actually rare it is needed in practice, and when it is needed, it's either for documenting foreign code's usage of pointers (i.e. non-Odin code), or it's for things which are not pointers at all (in Odin code).

The second option is a subtle one: it forces a specific style and architectural practices whilst programming. Odin is designed around two things things: to be a C alternative which still feels like C whilst programming and "try to make the zero value useful", and as such, a lot of the constructs in the language and core library which are structured around this. Odin is trying to be a C alternative, and as such it is not trying to change how most C programmers actually program in the first place. This is why you are allowed to declare variables without an explicit initializer, but the difference to that of C is that variables will be zero-initialized by default (you can do `x: T = ---` to make it uninitialized stack memory, so it is an opt-in approach).

Fundamentally this idea of explicit individual-value based initialization everywhere is a viral concept which does lead to what I think are bad architectural decisions in the long run. Compilers are dumb---they cannot do everything for you, especially know the cost of the architectural decisions throughout your code, which requires knowing the intent of your code. When people argue that a lot of the explicit initialization can be "optimized" out, this is only thinking form a local position of individual values, which does total up to being slower in some cases.

To give an example of what I mean, take `make([]Some_Struct, N)`, in Odin, it just zeroes the memory because in some cases, it is literally free (i.e. `mmap` must zero). However, when you need to initialize each value of that slice, you are not turning a O(1) problem into a O(N) problem. And it can get worse if each field in the struct also needs its own form of construction.

But as I said in my original comment, I do not think the `nil` pointer problem, especially in Odin since it has other array constructs, is actually an empirical problem in practice. I know a lot of people want to "prove" things whatever they can at compile-time, but I still have to test a lot of code in the first place, and for this very very specific example, it is a trivial one to catch.

P.S. This "point" has been brought up a lot before, and I do think I need to write an article on the topic explaining my position because it is a bit tiring rewriting the same points out each time.

P.P.S. I also find this "gotcha" people bring up is the most common one because it is _seems_ like an obvious "simple" win, and I'd argue it's the exact opposite of either "simple" and even a "win". Language designing is all about trade-offs and compromises as there is never going to be a perfect language for anyone's problem. Even if you designed the DSL for your task, you'll still have loads of issues, especially with specific semantics (not just syntax).

gingerBill··on Odin: Moving Towards a New "core:OS"
Directly from the FAQ: https://odin-lang.org/docs/faq/#is-odin-just-a-language-for-...

> Is Odin “just” a language for game development? # > No. It is a common misconception that Odin is “just” for game development (“gamedev”) due to the numerous vendor packages that could be used in the aid of the development of a game. However, gamedev is pretty much the most wide domain possible where you will do virtually every area of programming possible. > > Odin is a general purpose language; is capable of being used in numerous different areas from application development, servers, graphics, games, kernels, CLI/TUIs, etc. > > There are many aspects of Odin which do make working with 2D and 3D related operations (which are common in gamedev) much nicer than other languages, especially Odin’s array programming, swizzling, #soa data types, quaternions and matrices, and so much more niceties which other languages do not offer out-of-the-box.

gingerBill··on Odin: Moving Towards a New "core:OS"
I think the notion that "null" is a billion dollar mistake is well overblown. NULL/nil is just one of many invalid memory addresses, and in practice most of invalid memory address are not NULL. This is related to the drunkard’s search principle (a drunk man looks for his lost keys at night under a lamppost because he can see in that area). I have found that null pointers are usually very easy to find and fix, especially since most platforms reserve the first page of (virtual) memory to check for these errors.

In theory, NULL is still a perfectly valid memory address it is just that we have decided on the convention that NULL is useful for marking a pointer as unset.

Many languages (including Odin) now have support for maybe/option types or nullable types (monads), however I am still not a huge fan of them in practice as I rarely require them in systems-level programming. I know very well this is a "controversial" opinion, but systems-level programming languages deal with memory all the time and can easily get into "unsafe" states on purpose. Restricting this can actually make things like custom allocators very difficult to implement, along with other things.

n.b. Odin's `Maybe(^T)` is identical to `Option<&T>` in Rust in terms of semantics and optimizations.

gingerBill··on Context: Odin’s Most Misunderstood Feature
The code example is more to show the scoped copy-on-write behaviour of `context` more than how it is used in practice. I agree it might be a bit confusing and thus needs to be made clearer that is what the code example is meant to show. However, I don't there is any code example that could show "correct usage" of `context` without it defeating the point of it. As I say in the article, it makes more sense to leave it "confusing" because then people will ignore it.

The Overview is just that, an "Overview" and it's not meant be either a spec, a heavily detailed tutorial, nor an explanation of why a language construct is designed the way it is and/or why it exists. The latter of which would probably be as long as the Overview for each construct that exists if that.

gingerBill··on Context: Odin’s Most Misunderstood Feature
There is sadly a habit which is not bound to any "community", and I've seen a lot of cases where people will just rant a lot about something they don't understand when that rant could have been easily prevented by either reading the documentation/manual or asking someone in the first place. In the case of Odin, this is usually reading the Overview, the FAQ, or even just asking a question politely on the Discord/Forum/email. The implicit `context` system is one of those specific cases which is more likely to bring up an "uninformed rant". A lot of people seem to think you can figure everything out without reading a manual or rely on the veracity of what an LLM produces, and sadly this is not going to work for a lot of things in life. Most of the cases for explaining the existence of `context` (the thing the rant usually happens about) is usually solved by copying and pasting the two paragraphs from the Overview, explaining that it is for third-party interception. Sometimes it requires a longer explanation and thus I resorted to writing this article.

I don't like writing articles in general, since I am not a very good writer either, which is why I didn't want to write it; not because of the topic in itself. I could rephrase that first sentence/paragraph to not sound as "harsh" but when working on an open project, I would like people to at least read some form of documentation or just ask a question directly before they complain/rant.

gingerBill··on Context: Odin's Most Misunderstood Feature
I am the author of the article. If you have any questions, please feel free to ask :)
gingerBill··on The Titania Programming Language
If you want single pass, then you have to do it on a per block basis at the most (e.g. C89).

But this is not meant to be a fully fledged language, it's meant to be a teaching tool. If you want a fully fledged language that allows for out of order declarations, try Odin!

Also, the syntax of Oberon/Pascal doesn't really allow for it in a nice way. It kind of looks really weird when you allow for it out of order.

gingerBill··on The Titania Programming Language
I know Oberon does return things from certain procedures but I might not. I know the grammar allows for it but again, this is subject to change.

As for code generation, direct machine code to a Windows AMD64 PE executable.

Backend should not be that difficult because I am not working on anything complex nor optimizing. This won't be an optimizing compiler backend course.

gingerBill··on The Titania Programming Language
I only added that a few minutes ago, and it's a question of whether I should or not. This project is so goddamn new that I have not even decided anything. I was not expecting anyone posting this to HackerNews in the slightest.

Also this isn't JS-style ASI technically speaking, and it won't have any of the problems either. The syntax for this language is different enough that it won't be a problem. Procedures don't even return things.

gingerBill··on The Titania Programming Language
This has nothing to do with "dogma" and something simpler. It has nothing to do with "immediately see them".

Hint: This about this from a single pass compiler basis and how much memory needs to be reserved from the procedure's stack frame.

gingerBill··on The Titania Programming Language
That was the idea.
gingerBill··on The Titania Programming Language
And removing unnecessary keywords and modernizing it too. `[N]T` for arrays and `^T` for pointers, rather than `array N of T` and `pointer of T`. And supporting C++ style code `/*/` and `//`.

And as I develop this, I'll tweak it more so that people can actually understand without having to know the full histories of Pascals or Oberons or whatever.

gingerBill··on The Titania Programming Language
Completely independent of Odin (except being written in Odin). It's a plan to be a teaching tool to learn compiler development, that's it.
gingerBill··on The Titania Programming Language
Please note the project isn't even 24 hours old yet.

But I am using Oberon-07 as base, and I might deviate from it quite soon too. But I won't be going in the direction of things like Oberon+ (which adds generic and OOP programming) or Micron which adds the entire type system necessary to interact with foreign code. I just wanted something to explain to people how to do tokenizing, parsing, semantic checking (not just basic types), and machine code generation, and this seemed like the best language to choose.

n.b. I know the name does comes from from the Voyager space probe, but I wanted to keep it directly related somehow, and Titania was the best fit. It's also a moon of Uranus, and there is a story relation to Oberon (Fairy King).

← PreviousPage 2 of 9Next →