this post was submitted on 19 Apr 2026
0 points (50.0% liked)

Programming

26579 readers
252 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities !webdev@programming.dev



founded 2 years ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
[โ€“] sidelove@lemmy.world 4 points 9 hours ago* (last edited 9 hours ago) (1 children)

Hmm, I mean I totally understand the overlap in functionality. Especially when you get into the Java Lombok situation where annotations are as structural as the modifiers themselves. But there are clear cases in things like Python and Rust where the modifiers are a clear meta-programming that are mostly outside the scope of the language itself.

Granted, Rust is a weird example where annotations tend to "graduate" to the language itself, like in the form of #[async], but that clear delineation of what's in the language itself and what's defined as post-processing still leaves it more readable than if we heaped a chunk of similar-looking-but-willdy-different-effect-wise tokens on top of our function/type definition. E.g.,

#[cfg(target_os = "windows")]
#[pub] #[async] fn some_func() {
    #[mut] let my_var = 3u2;
    // ...

Vs.

#[cfg(target_os = "windows")]
pub async fn some_func() {
    let mut my_var = 3u2;
    // ...

Like, I do get the similarity in function, but it's almost like why we have capitalization in our natural languages. Making language-defined features "louder" and more ingrained in the language itself makes sense, even if the border is fuzzy.

Edit: even going the other direction, and we do:

pub cfg(target_os = "windows") async fn some_func() {
    let mut my_var = 3u2;
    // ...

That homogenization is still a bit of a bitch to read

[โ€“] soc@programming.dev 1 points 50 minutes ago* (last edited 23 minutes ago)

I believe that if you start from an annotation-only stance, then you will look at the language, its defaults and possible extensions differently, because annotations are "visually" more expensive than slapping yet-another keyword on something.

I. e.:

  • "no" visibility modifier should probably mean "public"
  • defining the external API should move to the module-level altogether
  • we should probably use var instead of let mut
  • #[cfg(target_os = "windows")] is just bad design overall; put different targets into different folders: much easier, works better
  • async should not exist (though not related to annotations vs. modifiers, but because the whole idea is a language design dead-end)

Rust's syntax with #[...] is not that great in this regard, as it triples the amount of symbol involved for simple annotations compared to something using @....