Made with KolourPaint and screenshots from Kate (with the GitHub theme).

  • glorkon@lemmy.world
    link
    fedilink
    arrow-up
    12
    ·
    15 hours ago
    IT'S SHOWTIME
      I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE a
      GET TO THE CHOPPER a
        HERE IS MY INVITATION "ArnoldC is the best."
      ENOUGH TALK
      TALK TO THE HAND a
    YOU HAVE BEEN TERMINATED
    
  • barsoap@lemm.ee
    link
    fedilink
    arrow-up
    20
    arrow-down
    1
    ·
    edit-2
    14 hours ago

    The actual reason why let … in syntax tends to not use C-style “type var” like syntax is because it’s derived from the syntax type theory uses, and type theorists know about parameterised types. Generics, in C++ parlance, excuse my Haskell:

    let foo :: Map Int String = mempty

    We have an empty map, and it maps integers to Strings. We call it foo. Compare:

    Map Int String foo = mempty

    If nothing else, that’s just awkward to read and while it may be grammatically unambiguous (a token is a name if it sits directly in front of =) parser error messages are going to suck. Map<Int,String> is also awkward but alas that’s what we’re stuck with in Rust because they reasoned that it would be cruel to put folks coming from C++ on angle bracket withdrawal. Also Rust has ML ancestry don’t get me started on their type syntax.

    • ulterno@programming.dev
      link
      fedilink
      English
      arrow-up
      0
      ·
      1 hour ago

      Until now, I looked at let and thought, “maybe they just felt like doing it that way”.
      Makes a lot more sense now.

    • weird@sub.wetshaving.social
      link
      fedilink
      arrow-up
      6
      arrow-down
      1
      ·
      15 hours ago

      There is also the thing where the compiler might mistake your c++ style variable declaration for a function, e.g.

      String myfunction():

      String myvariable();

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

    Good, now invent a keyword for variables you don’t want to declare the type. And now that you have a mix of keywords and identifiers on the same place, you can never update your language again.

    Also, make the function declarations not use a keyword too, so you get the full C-style madness of code that changes meaning depending on what libraries you import.

    • ZILtoid1991@lemmy.world
      link
      fedilink
      arrow-up
      4
      ·
      17 hours ago

      Good, now invent a keyword for variables you don’t want to declare the type.

      auto. Also in D, you only need const if you don’t want to specify a type for a constant, the compiler automatically inferres it to you.

      Function declarations can be easily decyphered from context, no problem.

      • ulterno@programming.dev
        link
        fedilink
        English
        arrow-up
        0
        ·
        1 hour ago

        Maybe that’s what the people developing spoken languages thought, while normalising conversations overdependent on context.

        But hey, now we have another comedic tool in anime.

    • stingpie@lemmy.world
      link
      fedilink
      arrow-up
      15
      ·
      1 day ago

      I don’t understand how not using a keyword to define a function causes the meaning to change depending on imports. I’ve never run into an issue like that before. Can you give an example?

      • marcos@lemmy.world
        link
        fedilink
        arrow-up
        8
        ·
        1 day ago

        Some declarations terminate on the name, other declarations go one requiring more tokens. In C, the only thing that differentiates them is the type.

        Parenthesis in particular are completely ambiguous. But asterisks and square brackets also create problems.

          • sushibowl@feddit.nl
            link
            fedilink
            arrow-up
            8
            ·
            16 hours ago

            The basic problem is that identifiers can be either types or variables, and without a keyword letting you know what kind of statement you’re dealing with, there’s no way of knowing without a complete identifier table. For example, what does this mean:

            foo * bar;
            

            If foo is a type, that is a pointer declaration. But if it’s a variable, that’s a multiplication expression. Here’s another simple one:

            foo(bar);
            

            Depending on how foo is defined, that could be a function call or a declaration of a variable bar of type foo, with some meaningless parentheses thrown in.

            When you mix things together it gets even more crazy. Check this example from this article:

            foo(*bar)();
            
            

            Is bar a pointer to a function returning foo, or is foo a function that takes a bar and returns a function pointer?

            let and fn keywords solve a lot of these ambiguity problems because they let the parser know what kind of statement it’s looking at, so it can know whether identifiers in certain positions refer to types or variables. That makes parsing easier to write and helps give nicer error messages.

            • BehindTheBarrier@programming.dev
              link
              fedilink
              arrow-up
              1
              ·
              edit-2
              11 hours ago

              I feel this is related, and hightlight this even further, look at all the ways to initialize something in C++.

              https://www.youtube.com/watch?v=7DTlWPgX6zs

              If you are really lazy, have a look at making an int at around 7:20. It’s not horrible that alone, but it does show how many meanings each thing has with very little difference, added on top of years of legacy compatability accumulation. Then it further goes into detail about the auto use, and how parantheses, bracket, squiggly bracket all can be used and help with the mess.

    • piccolo@sh.itjust.works
      link
      fedilink
      arrow-up
      9
      arrow-down
      1
      ·
      edit-2
      1 day ago

      In C#, you can use ‘var’ to have an impilict type variable.

      String name = “”

      var name = “”

        • sus@programming.dev
          link
          fedilink
          arrow-up
          16
          ·
          edit-2
          1 day ago

          So I think it’s still probably unclear to people why “mix of keywords and identifiers” is bad: it means any new keyword could break backwards compatibility because someone could have already named a type the same thing as that new keyword.

          This syntax puts type identifiers in the very prominent position of “generic fresh statement after semicolon or newline”

          …though I’ve spent like 10 minutes thinking about this and now it’s again not making sense to me. Isn’t the very common plain “already_existing_variable = 5” also causing the same problem? We’d have to go back to cobol style “SET foo = 5” for everything to actually make it not an issue

          • AnotherPenguin@programming.dev
            link
            fedilink
            English
            arrow-up
            3
            ·
            22 hours ago

            At least in C#, you can define variables with keyword names like this:

            var @struct = “abc”

            I think in Kotlin you can do the same, and even include spaces with backticks like val abstract class = “abc”

            I’m not sure if other languages allow that, regardless it should be rarely used.

            • pivot_root@lemmy.world
              link
              fedilink
              arrow-up
              3
              ·
              21 hours ago

              Swift also uses backticks and Rust has a dumb one in the form of r#thekeyword. Still much better than introducing a async as a new keyword in a minor version of a language and breaking a bunch of libraries.

          • piccolo@sh.itjust.works
            link
            fedilink
            arrow-up
            3
            ·
            1 day ago

            Ah I was misunderstanding the problem. And learned something new about C#, seems in order to avoid breaking existing code they introduce “contextual keywords” var being added later, it is a contextual. You can create a class ‘var’ and the compiler will prefer it.

    • pivot_root@lemmy.world
      link
      fedilink
      arrow-up
      15
      ·
      edit-2
      22 hours ago

      Rust is verbose, but C++ might still take the cake with its standard library templates. Especially when using fully-qualified type names…

      auto a = ::std::make_shared<::std::basic_string<char, ::std::char_traits<char>, MyAllocator<char>>>();

      A reference-counted shared pointer to a string of unspecified character encoding and using a non-default memory allocator.

      • calcopiritus@lemmy.world
        link
        fedilink
        arrow-up
        3
        ·
        11 hours ago

        fully qualified type names make any language awful.

        Here’s the same example in rust:

        let a = std::rc::Rc::new(std::vec::Vec<u8, MyAllocator>::new());

        I believe u8 also comes from a module, so it would be something like std::u8::u8, but I’m not sure.

        • KubeRoot@discuss.tchncs.de
          link
          fedilink
          English
          arrow-up
          8
          ·
          10 hours ago

          Not when taken to such an extreme so as to obfuscate the meaning and behavior of code, and make it difficult to understand how you would arrive at that code.

          Sane defaults serve to reduce verbosity without obfuscating meaning, simpler syntax with different ordering and fewer tokens reduce verbosity to make the code easier to read by reducing the amount of text you have to pay attention to to understand what the result is.

          I imagine there’s also a distinction to be made between verbosity and redundancy - sometimes extra text might fail to carry information, or carry information that’s already carried elsewhere. I’m not sure where the line should be drawn, because sometimes duplicate information can be helpful, and spacing out information with technically meaningless text has value for readability, but I feel like it’s there.

          • acargitz@lemmy.ca
            link
            fedilink
            arrow-up
            1
            ·
            edit-2
            7 hours ago

            Frankly, I have way more often ended up scratching my head for some cryptic piece of syntax than the opposite. Sure I could sit down and spend the rest of my life learning each language designer’s favourite syntax optimisations, but I kinda don’t want to. I’m a human, not a parser.

            And frankly, a good IDE editor should be able to fold/unfold verbose syntax. Better for it then to be there and folded, than for it to not be there and for someone to have to work backwards the intendrd meaning of every single line of code.

        • pivot_root@lemmy.world
          link
          fedilink
          arrow-up
          2
          ·
          edit-2
          20 hours ago

          std::string doesn’t have a template type for the allocator. You are stuck using the verbose basic_string type if you need a special allocator.

          But, of course, nobody sane would write that by hand every time. They would use a typedef, like how std::string is just a typedef for std::basic_string<char, std::char_traits<char>, std::allocator<char>>. Regardless, the C++ standard library is insanely verbose when you start dropping down into template types and using features at an intermediate level. SFINAE in older versions of C++ was mindfuck on the best of days, for example.

          Don’t get me wrong, though. I’m not saying Rust is much better. Its saving grace is its type inference in let expressions. Without it, chaining functional operations on iterators would be an unfathomable hellscape of Collect<Skip<Map<vec::Iter<Item = &'a str>>>>

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

            As long as you call .collect() on it at the end, don’t need to write the entire type as it is a method with a generic parameter, and returns that generic.

            The intermediate iterators though, those are hell. Especially if you pass it to a lambda and for some reason rust can’t infer the type.

            I once came across a parsing library that did the parsing with basically just the type system. It was absolute hell to debug and build. Types of parsers would be hundreds of characters long. It would take tens of minutes to build a simple parser.

            I don’t know much much time it would take to build a complex parser, since it was unable to. it reached the max type generic depth of the rust compiler, and would just refuse to compile.

            I believe it was called Chomsky or Chumsky or something like that. Discovering nom was a blessing.

          • Ajen@sh.itjust.works
            link
            fedilink
            arrow-up
            4
            ·
            20 hours ago

            Yeah, I missed the custom allocator at first. I thought I deleted my comment fast enough, but I guess you were faster. :)

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

    You’re encoding more information in the typescript one. You’re saying it’s a string that will get updated.

    • masterspace@lemmy.ca
      link
      fedilink
      English
      arrow-up
      31
      arrow-down
      1
      ·
      1 day ago

      Yeah, it’s explicitly distinct from const a: String which says it won’t change, and var a: String, which means this is legacy code that needs fixing.

        • Hotzilla@sopuli.xyz
          link
          fedilink
          arrow-up
          3
          ·
          edit-2
          22 hours ago

          True, but var and let are not same in js, so there is three.

          if(true) {

          var a = "dumdum"

          }

          console.log(a)

          Is valid and functioning javascript. With let it is not.

    • Scoopta@programming.dev
      link
      fedilink
      arrow-up
      17
      arrow-down
      2
      ·
      1 day ago

      You aren’t though. In most languages that use the latter declaration you would prefix the declaration with final or const or the like to specify it won’t be updated.

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

        It’s also valid rust syntax.

        But if it were rust, this meme would not make sense, since you would just type let a and type inference would do its thing. Which is much more ergonomic.

        • Victor@lemmy.world
          link
          fedilink
          arrow-up
          1
          ·
          16 hours ago

          Type inference is a pretty big thing in TypeScript as well though. In fact it’s probably the biggest thing about it, IMO.

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

            I don’t know typescript. But if that’s the case, this meme doesn’t make much sense.

            Who writes the types of variables in a language with type inference unless forced by the compiler?

            • Victor@lemmy.world
              link
              fedilink
              arrow-up
              1
              ·
              9 hours ago

              Maybe it’s a language without type interference?

              Either way, it sometimes makes sense in TypeScript to help the type system out a little bit.

              let array: string[] = [];
              

              In this situation, the type system can’t infer that the empty array should be a string array, because there are no items to go by.

            • nebeker@programming.dev
              link
              fedilink
              English
              arrow-up
              1
              ·
              2 hours ago

              And bow to the compiler’s whims? I think not!

              This shouldn’t compile, because .into needs the type from the left side and let needs the type from the right side.

    • Hotzilla@sopuli.xyz
      link
      fedilink
      arrow-up
      2
      ·
      22 hours ago

      C# has const string a = “Hello, World”;

      var in js is legacy, and default should be let, but changing that would break everything

  • DreamButt@lemmy.world
    link
    fedilink
    English
    arrow-up
    21
    ·
    edit-2
    1 day ago

    Because sometimes that let can be replaced by other things like const. Which can be managed statically by the machine and not by my (imperfect) ability to know if it’s mutated or not

    • lobut@lemmy.ca
      link
      fedilink
      arrow-up
      4
      ·
      1 day ago

      I think you can do const thing = ... as constto lock down the mutation?

      • ZILtoid1991@lemmy.world
        link
        fedilink
        arrow-up
        3
        ·
        17 hours ago

        So is let in some languages. In Rust, you have to constantly opt out from immutability with let mut, which makes writing more procedural code feel like you’re fighting with the compiler, and otherwise I don’t really see the rationale behind full functional coding. I only had a bug caused only once by unwanted mutation, the hardest part fixing it was to learn the proper use of my debugger tool.

    • Scoopta@programming.dev
      link
      fedilink
      arrow-up
      1
      ·
      1 day ago

      Ok but, in the second example you typically just put final or const in front of the type to denote immutability. I still don’t see the advantage to the first declaration.

      • DreamButt@lemmy.world
        link
        fedilink
        English
        arrow-up
        2
        ·
        1 day ago

        oh for sure, but I think that’s the rarer case for language implementions. Having a consistent structure with alternative keywords in static positions is just easier to develop an AST for. Personally my favorite language doesn’t even allow for const values (except by convention) so it’s really just a matter of preference

        • Scoopta@programming.dev
          link
          fedilink
          arrow-up
          1
          ·
          1 day ago

          Is it rarer? I think a lot of modern languages go for the first option but pretty much all C style languages use the latter. It’s probably a wash for which is more popular I’d think.

          • DreamButt@lemmy.world
            link
            fedilink
            English
            arrow-up
            1
            ·
            1 day ago

            I’m talking about quantity not the popularity of a given language. There are certainly a number of popular languages that follow that convention

  • JakenVeina@midwest.social
    link
    fedilink
    arrow-up
    10
    ·
    edit-2
    1 day ago

    Not to short-circuit the joke, but in this case, it’s because the valid JavaScript version is…

    let a
    

    …and one of TypeScript’s main design goals is to be a superset of JavaScript, that only adds syntax, and doesn’t re-write it.

    Beyond that, it’s probably a case of some new language just using what the designer is familiar with.

    • HiddenLayer555@lemmy.mlOP
      link
      fedilink
      English
      arrow-up
      30
      arrow-down
      1
      ·
      edit-2
      1 day ago

      It’s commonly used in math to declare variables so I assume programming languages borrowed it from there.

      • chaos@beehaw.org
        link
        fedilink
        arrow-up
        7
        ·
        22 hours ago

        More specifically, they’re borrowing the more mathematical meaning of variables, where if you say x equals 5, you can’t later say x is 6, and where a statement like “x = x + 1” is nonsense. Using “let” means you’re setting the value once and that’s what it’s going to remain as long as it exists, while “var” variables can be changed later. Functional languages, which are usually made by very math-y people, will often protest the way programmers use operators by saying that = is strictly for equality and variable assignment is := instead of == and = in most C-style languages.

      • bandwidthcrisis@lemmy.world
        link
        fedilink
        arrow-up
        7
        arrow-down
        1
        ·
        1 day ago

        BASIC uses (used?) it to declare variables. (I don’t know if earlier languages did.)

        Not that that’s a reason for other languages to copy it.

          • dan@upvote.au
            link
            fedilink
            arrow-up
            10
            ·
            edit-2
            1 day ago

            Older variants used DIM for arrays and LET for other variables. DIM was originally called that because it was setting the dimensions of the array.

            In modern BASIC variants, DIM has become a backronym: “declare in memory”.

            • sbv@sh.itjust.works
              link
              fedilink
              English
              arrow-up
              6
              arrow-down
              1
              ·
              1 day ago

              In modern BASIC variants, DIM has become a backronym: “declare in memory”.

              TIL. I always thought it was a backronym for declare in (yo) momma.

            • marcos@lemmy.world
              link
              fedilink
              arrow-up
              2
              ·
              1 day ago

              Even older variants required both a let to declare the variable and a dim to set its size.

              I remember a REDIM command, but I really can’t remember what basic it’s from.

              • dan@upvote.au
                link
                fedilink
                arrow-up
                2
                ·
                1 day ago

                The first programming language I used was Visual Basic (both VBA in Excel, and VB3 then VB6). I think it used redim to resize arrays.

      • tisktisk@piefed.social
        link
        fedilink
        English
        arrow-up
        6
        ·
        1 day ago

        I doubted you until I got about halfway through this whole page. I concede tho–you are most correct lol Still a decent read and for that I thank you

  • dan@upvote.au
    link
    fedilink
    arrow-up
    7
    ·
    1 day ago

    Can we talk about PHP functions with typehints too?

    public static function foo(): string {
    

    Practically every other language with similar syntax does this instead:

    public static string foo() {
    
      • dan@upvote.au
        link
        fedilink
        arrow-up
        1
        ·
        edit-2
        1 day ago

        TypeScript doesn’t need the “function” keyword for a method in an object or on a class though.

        const foo = {
          bar(): string {
           ... 
          } 
        }
        

        which I assume is doable because the syntax is unambiguous.

        PHP’s object orientation is similar to languages like Java and C#, which is what I was comparing to.

        • marlowe221@lemmy.world
          link
          fedilink
          English
          arrow-up
          1
          ·
          18 hours ago

          I believe the reason a function or method in an object does not need the “function” keyword has to do with the fact that JS is built on the prototype model and the fact that functions are first class in JS.

          As the saying goes, “Everything is an object in JavaScript…” (which is not strictly true).

        • sbv@sh.itjust.works
          link
          fedilink
          English
          arrow-up
          1
          arrow-down
          1
          ·
          23 hours ago

          Your example didn’t mention the use of the function keyword. Instead, it seemed to be questioning the placement of the return type - placing it after the argument list seems pretty common in newer languages.

    • HiddenLayer555@lemmy.mlOP
      link
      fedilink
      English
      arrow-up
      6
      ·
      1 day ago

      TIL PHP has statics.

      Also, does PHP actually enforce the type declarations? I’d assume it would but knowing PHP…

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

      JavaScript (Typescript for the type part) and python, the most popular scripting languages, use the same order as PHP.

      It’s usually compiled languages that do the other one.

      • dan@upvote.au
        link
        fedilink
        arrow-up
        2
        ·
        1 day ago

        TypeScript doesn’t need the “function” keyword for a method in an object or on a class though.

        const foo = {
          bar(): string {
           ... 
          } 
        }
        

        which I assume is doable because the syntax is unambiguous.

        In PHP’s case, the method syntax should also be unambiguous.

  • Oisteink@feddit.nl
    link
    fedilink
    arrow-up
    2
    ·
    1 day ago

    First time i used let it was to inline variable declaration with assignment . Can’t remember the language.