• bradboimler@lemmy.world
    link
    fedilink
    English
    arrow-up
    2
    ·
    14 hours ago

    I’ve toyed with building my own programming language. And, yeah, it uses annotations and no modifiers.

  • sidelove@lemmy.world
    link
    fedilink
    arrow-up
    5
    ·
    1 day ago

    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.devOP
      link
      fedilink
      English
      arrow-up
      1
      arrow-down
      1
      ·
      edit-2
      15 hours 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
        instead put different targets into different folders: much easier, works better
      • async should not exist at all
        (though not related to annotations vs. modifiers, but because the whole idea is a language design dead-end)


      So the code from your example would literally be …

      fun some_func: Unit = {
          var my_var = 3u2
          // ...
      

      … in my design.

      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 @....

      • sidelove@lemmy.world
        link
        fedilink
        arrow-up
        3
        arrow-down
        1
        ·
        13 hours ago

        Jfc that’s a bit of a stretch. You basically just said “you are wrong to use those features, and if you don’t use those features then my solution is great”. Like yeah, no shit, if I wanted a toy language I’d go back to using Logo.

        “no visibility modifier” should probably mean “public”

        For-fucking-real?

        instead put different targets into different folders: much easier, works better

        Ahh, yes, file-based programming, the most usable and ergonomic pattern for cross-cutting concerns. /s

        async should not exist at all

        The most I’ll give you there is that it’s used more frequently than it should. But it is far and away the best abstraction for bare-metal concurrency without a runtime. Your “dead end” comment reeks of writing off an entire language feature because you don’t understand it or why it solves problems no other language feature solves as well.

        Normally I’m open to discussing the merits and comparing drawbacks to certain approaches, but of course I’m going to be cross if you dump a bunch of confident horseshit on me. Like, wtf man??

        • soc@programming.devOP
          link
          fedilink
          English
          arrow-up
          1
          arrow-down
          1
          ·
          edit-2
          12 hours ago

          I spent the necessary effort to experiment/work with the various approaches to form an opinion, and your main counter argument is largely … being sarcastic, trying the hardest to misunderstand things to ridicule them and being generally offended?

          Let’s end this here, your comments are a poor use of my time.

          • sidelove@lemmy.world
            link
            fedilink
            arrow-up
            3
            ·
            edit-2
            12 hours ago

            Statements like “async is a language design dead-end” is the confidently correct misinfo that I’m talking about. You can’t expect anyone to take you seriously if you authoritatively present your opinions as gospel.

            Should I instead have interpreted it as “async is a language design dead-end, and by dead-end I mean overfitted standard for the problem space?” Because I really have to be charitable and put words in your mouth to paint your argument in a good light.

  • calcopiritus@lemmy.world
    link
    fedilink
    arrow-up
    5
    arrow-down
    2
    ·
    1 day ago

    What is this article? There is no author, and it is written as if it were an objective truth when it is clearly subjective.

    There is no conclusion, it’s just an introduction paragraph that says “do this, this is good design”, followed by a pro-con analysis, and then the article just ends. Given that it has real drawbacks, you would think it would be more nuanced than “do this, this is good design”.

    Furthermore the analysis is not even complete. The only 2 drawbacks mentioned only affecting the developer of the language. And ignoring more obvious drawbacks that would affect the users of the language:

    • Aesthetics. Annotations are just uglier than modifiers. Due to their special syntax instead of just a naked keyword.
    • Annotations take up more space. Screen space is valuable, annotations usually are stacked vertically, which takes up a lot of vertical screen space. This is in order to mitigate their use of horizontal screen space by their syntax.
    • Disorder. Annotations are not ordered, which means they are harder to parse by a human. And if there is a wall of annotations, a human might miss an important one because it is surrounded by others that are just boilerplate.
    • “Downgrading” modifiers to annotations removes their perceived importance. Modifiers modify the class/function/whatever, annotations add to it. Usually, you can ignore annotations and just look at the modifiers. If modifiers are annotations, you have to read the annotations to filter which ones are important to you and which aren’t. Which is harder to do due to the previous point “Disorder”.
    • If annotations were objectively better than modifiers, the logical conclusion would be “your language should not have modifiers, do annotations instead” instead of “if your language has both, remove modifiers”.
    • Namespacing is not objectively better. I don’t want to import “public” in every single file. It’s just useless boilerplate at that point. And some dependency might export their own “public”. Or even worse, a non-annotation (function, class) named “public”. If reserving keywords for modifiers is a concern, you can just prepend the uncommon ones with “__”. Nobody is going to complain that they can’t use the name “__readonly” because it’s reserved.
    • Variable declarations do have modifiers too (for example “const” in C). Annotations are awful for variable declarations. See the point about screen space. Same for closures or code blocks.
    • soc@programming.devOP
      link
      fedilink
      English
      arrow-up
      1
      arrow-down
      2
      ·
      edit-2
      12 hours ago

      You do not have to agree with every blog post found on the internet.
      I think you make a few good arguments, but you are way too angry for me to engage.

      • calcopiritus@lemmy.world
        link
        fedilink
        arrow-up
        2
        ·
        18 hours ago

        I did not intend to sound angry. I was trying to do an honest review of this article. Since I did not consider it good at all.

        • soc@programming.devOP
          link
          fedilink
          English
          arrow-up
          1
          arrow-down
          1
          ·
          edit-2
          16 hours ago

          Ok, then here’s a short answer to your points:

          Aesthetics. Annotations are just uglier than modifiers. Due to their special syntax instead of just a naked keyword.

          If the language has annotations already, then you have paid the tax of having “special syntax” in your language in any case.
          (Except Swift maybe, which has “attributes” and more than 200 keywords.)

          Annotations take up more space

          I don’t consider this a drawback. In fact, many languages with modifiers have the same rules about modifier placement.
          I actually want annotations on their own line, such that all my actual keywords start at the same column.

          Disorder

          Many languages with modifiers have the exact same issue, and address the issue the same way I’d address it for annotations:
          Define a desired order of annotations and let the compiler/linter/IDE/formatter deal with it.

          Downgrading

          Let the IDE/editor pick a different color for you “more important” annotations, if you like.

          “your language should not have modifiers, do annotations instead” instead of “if your language has both, remove modifiers”

          That’s just nitpicking the wording. Ok.

          Namespacing … is not objectively better. I don’t want to import “public” in every single file.

          Then don’t? Most languages don’t make you import String either.

          Namespacing … Or even worse, a non-annotation (function, class) named “public”.

          Have a separate namespace for for annotations, or treat @ as part of the name.
          Though it’s not something I would spend effort on – sometimes the best answer to “X does not work” is “then don’t”.

          Variable declarations do have modifiers too (for example “const” in C).

          I replaced …

          const foo: Foo = ...
          

          … with …

          @constantValue
          let foo: Foo = ...
          

          … in my language a short while ago. It’s fine.

          • calcopiritus@lemmy.world
            link
            fedilink
            arrow-up
            1
            arrow-down
            1
            ·
            13 hours ago

            I’m not looking to argue about the importance of my points. I wouldn’t have listed so many in that case.

            The point I’m trying to make is that this is a very incomplete article, as it doesn’t seem that much thought was put on the downsides.

            A good article would’ve considered every angle. And so would probably conclude (if it had a conclusion) that the premise is incorrect, and the world of language design is more nuanced than “having both modifiers and annotations is bad language design”.

            And at that point, the article would’ve probably ended up being: when should annotations be used instead of modifiers?

            Many of the most popular languages have both modifiers and annotations:

            • Java
            • Rust
            • Python *Javascript

            C doesn’t have both because it doesn’t even have annotations. Idk about C++, but it either doesn’t have annotations (like C) or it should be in the list above

            All of those have been heavily criticized from a language design PoV. And I’ve never seen anyone complain about this. People genuinely don’t believe this to be an issue.

            The closest is public static int main() for java. But making them annotations would not fix that, only rearrange the issue vertically.

            • soc@programming.devOP
              link
              fedilink
              English
              arrow-up
              1
              arrow-down
              1
              ·
              11 hours ago

              The point I’m trying to make is that this is a very incomplete article, as it doesn’t seem that much thought was put on the downsides.

              I could mentioned additional points in favor for the same reason you mentioned your points against, but at some point one has to stop and decide whether any minor, additional points made would sway the overall verdict.

              Many of the most popular languages have both modifiers and annotations:

              I have a separate blog post in which I consider when “popularity” or “familiarity” should be considered when it comes to language design.

              People genuinely don’t believe this to be an issue. The closest is public static int main() for java.

              If you look at Java-inspired languages like Scala or Kotlin, neither of them have public (made the default) nor static (replaced by companion objects).