Of all the "Better C" programming languages I've tried so far, Odin is my favorite. Somehow it feels very ergonomic and familiar to a C programmer. Zig has many cool things, but I'm always second guessing myself and trying to figure out the "right" way to do things. But writing Odin is really nice and feels fun.
I have high expectations from Odin going forward, but there are some pain points hopefully will get resolved in the future.
- The toolchain is alright at best (I know this is being worked on right now).
- Discord only communication with the community. They're all very nice but sometimes I wish a lot of these discussions should be indexed by a search engine.
I started using Odin just recently, I'm very happy with it so far, it's exactly what I needed, a mix between Go (no garbage collector) and C, context system, bunch of allocators available, a sane module system (folder based) and tagged union.. very good stuff
I've been using odin on some side projects (mostly game dev). I narrowed down my choices to Odin and Zig. After building toy projects with both, I settled on Odin. I like that it feels fairly high level, but still gives you so much control over memory layout.
Tried it and enjoyed the simplicity and productivity. I wish I would have been able to do more with it but the lack of docs stopped me somewhere along the path. To me the overview page is not enough, it doesn’t go much into details. The packages documentation page is hard to navigate, you either know what you’re looking for or just get lost. Same for code examples. The only way to have a better grasp of some stuff is by asking on Discord, which I don’t like doing. It would be great if something like “The Odin book”(like rust has) goes live
Odin looks extremely appealing to me, but I am quite sad about the lack of methods, or more specifically, lack of guarantees about "dot-autocomplete" support in mainstream code editors. But I do think methods make code more concise and readable too ( object_verb(obj) vs. obj.verb() ). They are syntactic sugar worth having.
In 2023, tooling is at the point where RTFM is secondary for mainstream lang libraries (TFM being embedded into the editor in intelligent ways). I will not go back.
IIRC, the odin language server now has method "dot-autocomplete" support that will reformat it into the function call with the variable as the first parameter.
https://github.com/DanielGavin/ols
It is not just about getting a function from an object and then executing that function.
It is executing that function in the context of the object from which you get it, by utilizing the pseudo-variable "this" (or 'self' in Smalltalk) which refers to that object from which you got that function (a.k.a "method" in this case).
But definitely the ability to have editor-support for lookup of argument-types etc. is a great benefit too.
> It is executing that function in the context of the object from which you get it, by utilizing the pseudo-variable "this" (or 'self' in Smalltalk) which refers to that object from which you got that function (a.k.a "method" in this case).
Ignoring runtime polymorphism for the moment, there's nothing special about "this" or "self". It's just another function parameter. Consider how in Python it is actually explicitly declared as a parameter in the method declaration.
It is special in that when a method executes say in JavaScript, the 'this' has a very specific value even though you did not pass in an argument of that name nor did you ever assign a value to a local variable of that name. Depending on the language you use trying to assign to the (pseudo-) variable 'this' may or may not cause an error.
The "automatic" value 'this' has makes it special, different from other variables and arguments. That automatic value ties the method-call-syntax into the semantics of what it means to call a method as opposed to calling a free function.
This can be exemplified in JavaScript easily:
let funk = myOb.funk;
let v = myOb.funk();
let v2 = funk(); // throws error
In this case the error gets thrown if
myOb.funk internally refers to 'this'
and tries to access some field of it.
That causes an error because 'this' is
undefined inside 'funk' when it is called
as a plain function.
When you call myOb.funk() there is NO error
in the same case, because 'this' is then
NOT undefined, its value is 'myOb'.
You can access any field of myOb inside
the code of myOb.funk when you call it as
myOb.funk().
That is a big semantic difference, not
just "syntactic sugar".
> the 'this' has a very specific value even though you did not pass in an argument of that name nor did you ever assign a value to a local variable of that name.
It's just an implicit parameter named `this` whose argument happens to appear to the left of the `.` instead of after the `(`. Yes, there's a little extra work in the language to support this, but it's not particularly complex or deep semantically.
(In fact `this` is particularly semantically shallow in JavaScript because as your example notes, it's not even bound when a reference to a method is taken. In most other languages, `myOb.funk` will give you a function that partially applies `this`.)
That is not necessarily the case though, for instance in Self (the language) `self` is the parent slot of the method activation object which contains the instance to which the message resolved. Then again there's no to functions as I don't think Self has free functions.
Also lots of languages have syntactic sugar around the corresponding object e.g. implicitly dereference it for attribute access and method calls, or even give it exclusive(ish) properties like @ in Ruby (or straight up instance variable access in smalltalk).
Even Python treats it specially, given a method `foo`, `obj.foo` actually returns a proxy object which partially applies `foo` to `obj`. This only works on functions defined on the class object, mere callables set on the instance don't get that treatment.
> Also lots of languages have syntactic sugar around the corresponding object e.g. implicitly dereference it for attribute access and method calls
The parent comment specifically said "by utilizing the pseudo-variable 'this' (or 'self' in Smalltalk)", so I was referring to that. Yes, in languages where the receiver is implicitly added to the lexical scope chain, things get a bit more complex.
> or even give it exclusive(ish) properties like @ in Ruby (or straight up instance variable access in smalltalk). Even Python treats it specially, given a method `foo`, `obj.foo` actually returns a proxy object which partially applies `foo` to `obj`. This only works on functions defined on the class object, mere callables set on the instance don't get that treatment.
Sure, there's other features that object-oriented languages tend to hang off methods too, but my point was just that from the perspective of within a method body, the receiver's mostly just another parameter. This is made explicit in some languages:
In python you get more than just a self - you get easier access to the inheritance hierarchy - super() is actually a compiler supported language feature (the compiler secretly inserts the parent class intro the parens).
Those the two different syntaxes you can use to make a method-call. They have the same result for all arguments. So you can say one is syntactic sugar over the other. Their semantics are the same. In other words they have the exactly same meaning.
BUT if you write:
let v3 = myFunk();
the result is different. And you get an error if your source-code assumes that 'this' is not undefined.
That shows that the semantics of the 3rd example above is different from the semantics of the first two. In other words the semantics of a function-call and of a method-call are different. Therefore, we can say that method-call is not syntactic sugar for doing the same thing as a plain function-call.
Except we were never talking about JavaScript. I thought the OP made it pretty clear that they only cared about the syntax of method calls because they flow nicely and more easily support auto-complete in editors. Simple syntax sugar that translates `foo.bar(x, y)` into `bar(foo, x, y)` would suffice for both.
> Syntax sugar that translates `foo.bar(x, y)` into `bar(foo, x, y)`
For that to be syntactic sugar it would have to be the case that foo.bar(x, y) and bar(foo, x, y) always produce the same result for any given values of 'foo', 'x' and 'y'.
Editor suggestions are good enough when you know what you’re looking for or can guess where the method you’re looking for will be and what it will be called. You very much still need to RTFM if you don’t have neither
So let's say I'm using some new SDK. I run a method that returns a Service object. In my current Go/Python world, I can dot-autocomplete to quickly get an idea of what procedures I can perform with this object. 90% of the time, this is sufficient to proceed. 10% of the time I need to RTFM/SO.
Ooh, hadn't seen @disable before, super useful to know! That'll be handy for doing toggleable build options for tracing / debugging.
I've been using Odin for about a year now, many of the pain-points I've had have just been knowledge gaps. Odin's docs and debug info have slowly gotten better over time, and little discord-community tips here and there have made a huge difference for my quality of life.
I was curious after reading: can the @disable behavior be modified at runtime? For long running programs I find it helpful to be able to set a certain log level up front but have a way to update it without rebuilding or restarting the program. There may be other operations that can’t immediately be shut down and restarted so requiring a rebuild or restart to get debug logs is not an option in those cases.
Shaving the yak: I find `$FNAME.test.odin` to be a bit nicer than `$FNAME_test.odin`.
I'm confused about this caller_location thing in tests. It looks like you're just passing `loc = loc` a bunch of times for no good reason. Why can't the language automatically or implicitly implement that functionality? Having to write `loc = loc` at the end of every assertion just seems silly.
Sure, I'm saying the language could aspire to implement full stack traces automatically for tests, rather than requiring passing it for all assertions. Having to keep writing the same thing over and over is just boilerplate and a distraction. There's no reason the language itself couldn't implement some built-in support for such functionality along with the testing module, given that they control the full ecosystem.
How does one compile a language to other architectures which are not “officially” supported? It should be doable since it uses LLVM? Example, ESP32 SoC.
I can't imagine someone named their language "of", "programming", or "in". So, I guess 3. Joy and Odin are obvious since they have shown up here recently.
Totally tangential, but am I the only one that was taught to put punctuation inside of quotes and now despises that rule?
If you're referring to the period at the end of the sentence, I don't like that rule either.
Seems more natural to have the period after the closing quote, at least in cases like this sentence of yours from above:
>I can't imagine someone named their language "of", "programming", or "in".
But I think there may be cases where period inside and before closing quote may seem better, e.g. if quoting what someone said, like a quoted sentence inside another sentence.
I have a hard time recommending the book. The main character had no agency for most of it, and the plot was very unclear. It made for a good unveiling at the end, but given the size of the book...it's a lot to read for that payoff.
I won't say don't read it -- it did manage to keep my interest, after all -- I just have a hard time recommending it due to the time-investment:reward ratio.
I have high expectations from Odin going forward, but there are some pain points hopefully will get resolved in the future. - The toolchain is alright at best (I know this is being worked on right now). - Discord only communication with the community. They're all very nice but sometimes I wish a lot of these discussions should be indexed by a search engine.