Video: Odin for Go programmers

I’ve just uploaded this short (1hr) “Intro to Odin for Go programmers” video.

Currently it’s unlisted rather than public on youtube, as I’m hoping to sit on it on a bit before publishing. It came out a little longer than I was hoping, so maybe I’ll cut some things and/or re-record a few parts. If you have any feedback or corrections, please reply here.

4 Likes

There’s a minor typo in the title: “Into” rather than “Intro”.

I’ll reply as I watch along in “minutes-ish”:

  • 9ish, the d := .North is not allowed because it is possibly ambiguous. Your mental context isn’t the same as what the compiler would have to do to be consistent and coherent. “That context” is not really any different to any other context, and as such, if there is not type hint, it cannot determine it. To make it work as you initially expected, it would have to search through all of the constant declarations for an enum type and then check against each of them, and do that recursively across all parent scopes, which is going to be extremely costly for the compiler and unclear to the person reading too.

  • 11ish, @(rodata) does exist to have the equivalent of static const in C.

  • 17ish, the v == true bit is “odd” only because Odin has rules similar to Go with structs. In Go and Odin, structs are comparable if all of the fields are comparable. In Odin, a union is comparable if all of the variants are comparable, so what is happening is that it’s doing an implicit conversion of true to the union type, and then comparing the unions directly.

  • 18ish, case nil: is not necessarily the same as case:. case: would also handle the invalid/corrupted cases.

  • 20ish, the context is copy-on-write and is local to the scope, not just procedure (which you do correct around late 23ish)

  • 29ish, the value of an attribute can be anything pretty much. It depends on the attribute.

  • 32ish, Go technically has “untyped types” too, it’s just that they don’t necessarily explicitly state that in any of the docs.

  • 35ish, Go overloads the concept of a slice as in view and “slice” as in dynamic array. Go can get away with this because it has Garbage Collection. I think it’s a bad design but I understand why it exists the way it does.

  • 40ish, minor typo with “only exist at runtime” should be “only exist at compile time”, but technically that isn’t true. It’s kind of one of those things which just happens to be a technical type theory which is not that trivial to explain. Odin and Go both have a case which is if x == y {...}. In this case, the expression of x == y is an “untyped boolean” and that is its type at runtime too. This allows the compiler the choose the more appropriately sized value when doing the calculation to it more efficiently.

  • 53ish, the $ is only declared once to prevent people accidentally reusing declarations which they didn’t meant to use. It’s also there to make it clear that the use of the $ is for the declaration of its use, and to be used when you refer to T anywhere else.

  • 54ish, clamp is already a built-in procedure

  • 58ish, so the reason both cond ? x : y and x if cond else y exists is because x when cond else y exists. ?: is there mainly for pragmatic purposes of being familiar to C programmers, but it only has the semantics of if and not when. So if you need or require when like semantics, ?: would not be enough.

  • 59ish, Go has anonymous nested structs too.

  • 59ish, Go has type aliases type x = y

2 Likes

On enumerated arrays and their uses, you actually touched on something they are good for a minute earlier: non-integer values you want to associate, for example:

Direction :: enum {
    North,
    South,
    East,
    West,
}
directions :: [Direction]string{
    .North = "going north!",
    .South = "going south!",
    .East = "going east!",
    .West = "going west!",
}

On error unions and each having their own nil: exactly for these cases we have My_Union :: #shared_nil union {} which makes each case’s nil value be shared.

Nice video!

minor pickup: the assignment to north had ==

You mention Odin has no metaprogramming which is largely true. however i’d make the distinction that comp-time programming is what is more restricted. For context, the parser available in core; so its quite easy to do a metaprogram as a pre-pass. Many folks get in a tizzy over wanting ultra fancy rust macros or other system to do comp time. i’ve found it nicer to be a distinct phase.

There is the keyword when which is like a comptime if, it is quite useful and often scratches the comptime need.

1 Like

The video contains an error, as found by @Mr_47.

my_int: int // uninitialized global and a: int // uninitialized local are both zero-initialized.

To skip initialization, intialize it with ---, like so: a: int = ---. This is the same way we express the missing procedure bodies in foreign imports, i.e. foo :: proc (a, b: i32) -> c.int ---

2 Likes

I haven’t watched the video because YouTube is blocked and I’m too lazy to turn on VPN, but after programming in Odin for about a year or so, coming after that to Go just feels weird. Not having proper enums, camel-case-based publicity rules, explicitly-passed context really make it feel “rusty” (as in ferrum oxide III). And on top of that there are smaller features missing like or_return.

Go did make a step in the right direction with error handling (i.e. error handling is explicit), but still doesn’t solve the other problem (you have no idea what errors you’re supposed to handle), and it doesn’t allow some really useful things for propagating errors back.