[ $davids.sh ] — david shekunts blog

😐 Bun and even here messed up 😐

# [ $davids.sh ] · message #182

😐 Bun and even here messed up 😐

#js #nodejs #bun

  • @ [ $davids.sh ] · # 576

    Macros are a metaprogramming technique that allows you to run code at compile time, which generates code for runtime. It's a cool thing because it allows you to speed up both development and the code itself.

    But there's one BUT... you can call me a Go-lover, but damn, there's a second metaprogramming technique that has long been considered a more preferable version of macros – code generation.

    The difference is that macro code appears at compile time, while "code generation" code appears when you run it with a separate command.

    Exaggerating, you define a template, run the "go:gen" command, and your codebase expands with the necessary code.

    Among the advantages: the result is much safer, clearer, and more visible, you can customize the result, it allows you to implement incredibly optimized algorithms from templates, and much more.

    JS, you were given another chance, and you're still stepping on the same rake... damn it...

    The only thing that's pleasing: there's still a chance to write code generation yourself / find a library, but it's harder to add macros to the language yourself, so we consider it good that they at least did this.

  • @ Artur G · # 577

    In Go, they implemented code generation because their type system didn't allow for macros. If I'm not mistaken.

    Macros, on the other hand, are better suited for programming languages with a proper type system. 🙂 async/await is exactly that.

    And generally, let's just bury Bun already. Why do we need another runtime? 🥸

  • @ [ $davids.sh ] · # 578

    That's the point, the Go developers intentionally chose code generation following the principle of "explicitness and simplicity": write a template, generate code, check it, cover it with tests, and move on.

    Macros in this regard are closer to "magic and abstraction" (yes, they have their tricks too, but code generation is more needed and useful in my opinion).

    It's important to note that macros and "syntactic sugar" that can later transform into something else after compilation are different things (and I'm not against "sugar").

    I can't call "async / await" macros; it's just part of the language, or did I misunderstand?

    And let Bun live and develop; only if Node feels the heat will they start moving (otherwise, in the last two major releases, we've only gotten built-in Jest and fetch... pathetic).

  • @ Artur G · # 579

    I can't call "async / await" macros, it's just part of the language, or did I misunderstand?

    async/await sugar is converted into regular .then() chains internally. Don't you think it's strange that you can't do the same for other data types?

  • @ Artur G · # 580

    For example, for Promise<Option<T>>, it would be convenient to "await" the T value directly.

  • @ [ $davids.sh ] · # 581

    It used to be like that, but now async/await are language operators.

    The difference for me with "syntactic sugar" is that it's developed by people whose job is to create the compilation and this very sugar, and only contributors can add some new feature.

    And if you give macros to anyone, they will do anything with them, ultimately leading to what C++ developers complain about (i.e., a bunch of unmanaged macros).

  • @ [ $davids.sh ] · # 582

    Do you mean for the function to return "T" instead of "Promise<Option>"?

  • @ Artur G · # 583

    Yes, macros can be harmful. But, JS has plenty of practices that the community has successfully eradicated. They stopped doing monkey patching, didn't they?

  • @ Artur G · # 584

    Rather, so that after await it returns type T or the entire function returns Option.none if there is no value. So that I don't have to write if (Option.isNone(result)) { return Option.none } myself.

  • @ Artur G · # 585

  • @ [ $davids.sh ] · # 586

    I have very little trust in the Node.js community – many come from the frontend world, arrived to write on blockchains, or are building a startup on MongoDB + NestJS.

    Therefore, I'm always very afraid of giving extra to people I don't trust (again, this is my personal approach, which is why I like Go).

    But I understand the thought.

  • @ [ $davids.sh ] · # 587

    And here again, personally about my approach: I only like explicit, straightforward implementations)

    I'd rather write if (Option.isNone(result)) { return Option.none } a thousand times than use any kind of custom implicit construct.

    But this is purely my opinion, everyone chooses what's convenient for them here.

  • @ [ $davids.sh ] · # 588

    So yes, if such a construction would help you, then macros would be useful

    And for me, they are dangerous)

  • @ [ $davids.sh ] · # 589

    Let's do this: if such an operator (like !, which is also in Zig!) becomes part of the TS compiler first, and then part of the language, I'm all for it (like async / await once was).

    But if it's a custom macro written at some workplace, I'd be wary of that.

  • @ Artur G · # 590

    I'm afraid that will never happen. 🥲

  • @ [ $davids.sh ] · # 591

    Well, by the way, yes, I understand.

    I also thought that such an operator would actually be useful...