Remix.run Logo
tialaramex 3 days ago

The ergonomics of Odin are ghastly, it's all special cases all the time.

For example, in Rust when we write `for n in 0..10 {` that 0..10 is a Range, we can make one of those, we can store one in a variable, Range is a type. In Odin `for i in 0..<10 {` is uh, magic, we can't have a 0..<10, it's just syntax for the loop.

in Rust we can `for puppy in litter {` and litter - whatever type that is - just has to implement IntoIterator, the trait for things which know how to be iterated, and they iterate over whatever that iterator does. In Odin only specific built-in types are suitable, and they do... whatever seemed reasonable to Bill.

You can't provide this for your own type, it's a second class citizen and isn't given the same privileges as Odin's built-in types.

If you're Ginger Bill, Odin is great, it does exactly what you expected and it covers everything you care about but nothing more.

mattwilsonn888 2 days ago | parent [-]

It's called simplicity.

Not every single semantic element in the language needs to be a type.

`for i in 0..<10`

This isn't "magic," it's a loop that initializes a value `i` and checks against it. It's a lot less "magic" than Rust. The iterable types in Odin are slices and arrays - that is hardly arbitrary like you imply.

The type system in Rust is mostly useful for its static guarantees. Using it for type-gymnastics and unnecessary abstractions is ugly and performative.

Tasks in Odin can be accomplished with simplicity.

The C++ misdirection and unbounded type abstractions are simply not appreciated by many.

If you want a language with no special cases that is 100% fully abstract then program in a Turing machine. I'll take the language designed to make computers perform actions over a language having an identity crisis with mathematics research, all else equal. Unless I'm doing math research of course - Haskell can be quite fun!

Ginger Bill is a PhD physicist as well -- not that education confers wisdom -- but I don't bet his design choices are coming from a resentment of math or abstraction.

Absolute generality isn't the boon you think it is.

tialaramex 2 days ago | parent [-]

The "simplicity" you're so happy about means you only get whatever it is Bill made. If that doesn't work for Bill he'll fix it, but if it doesn't work for you (and at scale, it won't) too bad.

Far from just the two special cases you listed I count five, Bill has found need for iterating over:

Both built-in array types, strings (but not cstrings), slices and maps.

`for a, b in c { ... }` makes a the key and b the value if c is a map, but if c were instead an array then a is the value and b is an index. Presumably both these ideas were useful to Bill and the lack of coherence didn't bother him.

Maps are a particularly interesting choice of built-in. We could argue about exactly how a built-in string type should best work, or the growth policy for a mediocre growable array type - and Odin offers two approaches for strings (though not with the same support), but for maps you clearly need implementation options. and instead in the name of "simplicity" Bill locks you into his choice.

You're stuck with Bill's choice of hash, Bill's layout, and Bill's semantics. If you want your own "hash table" type that's not map yours will have even worse ergonomics and you can't fix it. Yours can't be iterated with a for loop, it can't be special case initialized even if your users enabled that for the built-in type, and of course all the familiar functions and function groups don't work for your type.

I don't have a use for a "language designed to make computers perform actions" when it lacks the fine control needed to get the best out of the machine but insists I must put in all the hard work anyway.