12_throw_away 3 months ago

I wish there were even more of this sort of thing, even though I'm an anti-braces zealot - it's crazy to me that, here in 2024, code is still so tightly linked to specific textual representations. Maybe there's an alternate reality where IDEs and development tooling got better and better post-smalltalk/lisp, instead of ... whatever we have now. Maybe we'd have editors and viewers where you could configure the syntax however you wanted. And sure, it would be persisted to disk in some canonical representation, maybe text, maybe a DB ... but you'd never need to worry about it, because all your tooling (VCS, diffs, refactoring tools, etc) would work with the AST, and you'd never need to worry about tabs or spaces ever again.

  • tkuraku 3 months ago

    I think having a single syntax is the best way. I don't want to have to look at python and have to parse spaces, curly braces, square braces, etc. It all being standard is really helpful. A standard Autoformatter like black or gofmt even though I might might not choose all the options, the uniformity is super valuable.

    • _the_inflator 3 months ago

      I agree. To me ESlint in the JavaScript domain is an unsung hero.

      Code is so incredibly hard to mentally grasp and every mental overload should be omitted to reflect on the logic.

      There is a reason why there is one code basis and this should always be curated by a linter to uniformly enforce a standard.

      There is still plenty of room for style and code organization.

      I witnessed first hand many trench wars around seemingly small things like curly brackets in IF statements dealing with the question of one white space or none, because it appealed to personal preferences and before ESlint people would go to great length reformatting hundreds of LoCs just to get their right feeling of code syntax.

      Weird. And git -diff was massive, as well as the code reviews.

      (Un)Happy times. :D

      • MrJohz 3 months ago

        I recommend Prettier over ESLint - Prettier tends to produce more consistent results and is a lot faster (because it's doing less work). Moreover, ESLint are deprecating the styling rules at the moment (although they'll be made available in a different package).

        You can configure ESLint to use prettier, but in my experience it's usually easier to just run ESLint separately to prettier.

      • hgomersall 3 months ago

        I finding reading other people's rust generally delightful because everyone is the same machine controlled style guide (cargo fmt + clippy). It's definitely reduces the mental burden of reading code.

    • dTal 3 months ago

      Your justification for a single syntax is "I don't want to have to look at python and have to parse spaces, curly braces, square braces, etc." But the comment you just replied to said:

      >Maybe we'd have editors and viewers where you could configure the syntax however you wanted

      I took this to mean that, in this fantasy universe, you could make any source file look however you want. Like tabs vs spaces and pure html vs html-with-css, this is about separating meaning from presentation. Is there a good reason to force the same visual representation on everyone?

      • jefftk 3 months ago

        > Is there a good reason to force the same visual representation on everyone?

        Leaky abstractions. If there are two different visual representations then sometimes someone using one representation will need to think about the other.

        • Spivak 3 months ago

          I think this is the best case against a more abstract notion of source code. I don't think you'll ever achieve the dream of heterogeneous representations on a single team unless you somehow get an autoformatter like black to work with both.

          • quectophoton 3 months ago

            There's also questions like:

            * Would such bytecode/binary be considered "source code"? If no, then bye bye Open Source Definition (OSD). Distributing such thing would not be considered open source.

            * If it is considered "source code", then is it considered "obfuscated" source code? If yes, then bye bye OSD. Distributing such thing would not be considered open source.

            * If it is not considered "obfuscated" source code, then what's the difference compared to, say, JVM bytecode? Is it only that an IDE exists that can modify such bytecode in a fancy way?

            * In that case, if such an IDE is created that modifies JVM bytecode directly, and a program is created using that IDE modifying the JVM bytecode[1] directly, and such "source code" is distributed, the would that bytecode be open source? Since, after all, it's "the preferred form in which a programmer would modify the program" (and therefore not obfuscated).

            [1]: Or maybe some superset that is mostly JVM bytecode but it has some opcodes for higher level niceties.

      • tkuraku 3 months ago

        You are right. It would be cool if that was an option, but it just seems like a lot of unnecessary complexity to actually make that happen. In addition if you ever want to look at code with a colleague on the same computer then the syntax becomes an issue again.

    • sverhagen 3 months ago

      This may be controversial, but I find 2-character indented Javascript, coming from my 4-character indented Java, for the projects I work on, as much of a shock as moving between braces and Python. Particularly if it has been subjected to an opinionated formatter that just doesn't match my personal style. Completely unreadable, I mumble under my breath. And then my eyes adjust to it for a bit, and after an... hour? (maybe) of coding in the (ahum) "hostile" style, it's familiar (again) and we're on our way.

      • dotancohen 3 months ago

        This is why I prefer tabs for indentation. I get to see 4 spaces, the blue haired frontend kid gets to see 2 spaces, and Linus gets to see 8. Everybody's happy.

        • leni536 3 months ago

          Sounds good in theory, but I never saw a project that used tabs and didn't look like a complete mess when viewed with the non-blessed tab width.

          • arp242 3 months ago

            It's fine as long as you don't use tabs for visual alignment. Especially C projects tend to do this, and/or have a weird mix of tabs and spaces (e.g. indent by four spaces, but all eight spaces are tabs). That's just silly.

            But if you just always indent by n tabs, and align with spaces for visual alignment, then it's not a problem. This is what e.g. gofmt does.

          • shakna 3 months ago

            Pretty sure the Linux source tree looks fine at a tab width of 2 instead of the blessed 8.

          • ahartmetz 3 months ago

            Emacs even "helpfully" auto-converts <tab width> spaces to one tab, no matter where.

        • RHSeeger 3 months ago

          The problem with tabs is that you can't really do alignment with them, unless you have elastic tabs (which are pretty much nowhere). I love the idea of tabs for indentation and spaces for alignment, but even bringing up the idea of using both gets one branded a heretic, so that's out. Which pretty much leaves only spaces if you want to allow for alignment.

          • MrJohz 3 months ago

            I'm really sceptical of the idea of mixing two different invisible characters in the same file, which is why the tabs+spaces idea makes me feel slightly icky. But another option is just not using alignment spaces at all - if you want to align two parameters/statements/etc, you always split them onto their own lines and use indents directly instead of alignment.

            In other words, instead of:

                def my_func(self,
                            param):
            
            You always do something like:

                def my_func(
                    self,
                    param,
                ):
            • dTal 3 months ago

              I tend to agree that you shouldn't be "aligning" things with spaces anyway. If nothing else, it causes diff pollution when the length of a line changes and you have to add or delete spaces to adjacent lines to keep things even, even though no semantic change to those lines has occurred.

              However, regarding "mixing two different invisible characters in the same file" - you can, and should, configure your text editor to display tabs in a visually distinct way from spaces. Kate (my favorite) shows them as chevrons. Geany and Notepad++ show them as arrows. Not only does this make it easier to scan vertically along an indentation level, but doing so also makes it glaringly obvious if a pesky space has snuck in, resulting in a jarring misalignment.

              • RHSeeger 3 months ago

                > If nothing else, it causes diff pollution when the length of a line changes and you have to add or delete spaces to adjacent lines to keep things even, even though no semantic change to those lines has occurred.

                While I agree with this in general, I find making the code nicer to read to be more important that avoiding diff pollution. Especially when that diff pollution can be avoided with a simple "ignore whitespace" in most cases.

              • MrJohz 3 months ago

                I get that if I'm truly mixing one and the other, but if I'm consistently using tabs for indentation, I mostly want them to be invisible - I don't want visual noise on every line. I guess if the syntax highlighting makes them subtle enough it could work, but I think that sort of visual distinction only really works if the visually distinct character only rarely shows up.

            • RHSeeger 3 months ago

              I tend to prefer the former, but it suffers from the indentation being way to large if the method name is really long.

              That being said, there are other cases where I want to align things and "a specific size indent" doesn't work

              SQL

                  SELECT this_column,
                         that_column
                  FROM tablename
                  WHERE this_column = 1
                    AND that_column IS NOT NULL
              
              Comments

                  /* 
                   * Blah blah blah
                   * Note: this is interesting because (enough text to want newline)
                   *       and also that blah blah
                   */
              
              There's lots of places where "alignment" makes sense.
              • MrJohz 3 months ago

                For the SQL case, you can just use a different formatting that puts aligned items into blocks, something like:

                    SELECT
                      this_column, 
                      that_column
                    FROM tablename 
                    WHERE
                      this_column = 1
                      AND that_column IS NOT NULL
                
                (The AND token could go either where it is, or at the end of the previous line, depending on your preferences - I prefer the clarity of putting the operator first here over the alignment of the column names, but I can see both sides.)

                It might not be your preference, but that's always going to be the case with formatting.

                With the comments, that's a good point. I'd generally prefer to use double comments for anything that spans multiple lines, but if you're creating a formatter you need to handle any syntax thrown your way. You could try formatting it without the leading space, but that would be very unusual, or keep the leading space and have it as the one exception to the rule. Or just not format comments, I guess.

          • segfaltnh 3 months ago

            For what it's worth, this is how the built in and mandatory Go formatter works and it's "fine".

        • the_other 3 months ago

          If you can also get your colleagues to do things like putting their `&&` style logical operators on new lines, then tabs for indents works really well.

          (This isn't the best example of what I'm getting at, but it's easy to grasp. A stronger example would be the use of ternary operators with multiple lines of JSX. There are many "micro-syntaxes" or "micro-layouts" that help readability and form common patterns in code bases which don't play well with tabs-for-indents, so when you use tabs, you have to train your team to develop and accept novel versions of these "micro-layouts".)

    • VirusNewbie 3 months ago

      > I don't want to have to look at python and have to parse spaces, curly braces, square braces, etc.

      But if the syntax was separate from the underlying representation, couldn't you just have your editor open it the way you want?

      • tkuraku 3 months ago

        That is true. That seems like a lot of complexity though.

    • thejohnconway 3 months ago

      The whole point is that you don't have to parse different syntax, because you choose your syntax at the editor level.

    • ok_computer 3 months ago

      +1 for ruff for python as a formatter & linter that allows single quotes without shaming you.

      I’m all for keeping consistent flat utf-8 files. I’d hate for my code ultra simpleminded, possible to pen test with a pen and paper, python and sql code to be wrapped in a god awful xml or json or proprietary db markup and object hierarchical model of what code should look like.

      Like I imagine trying to check in a jupyter notebook but worse.

      For instance tabs vs spaces was decided and text editors accommodated this and despite what may be someone’s personal preference a uniform decision was made.

      Humans can learn. We should use accessible formats and push for standards and keep those readable.

  • phaedrus 3 months ago

    I like to draw the comparison that in an alternate universe where the ASCII .txt file format had simply included a color byte with every letter byte, we'd now be having coding format guidelines that also go into great detail prescribing manual syntax highlighting. The fact we don't and avoided endless bike shedding over syntax highlighting, instead leaving it to automatic tools and the presentation layer not the code itself, is purely an historical accident. Well, what does that say about other code formatting details which programmers currently do waste time manually doing and worrying about?

    • pseudosavant 3 months ago

      I had never considered the bikeshedding that would occur if there was a color byte… We struggle with spaces versus tabs, how many spaces, braces (or not), semi-colon (or not).

      It would definitely be the norm that there were languages that were dark or light mode, and both sides would be convinced they were right.

      • mock-possum 3 months ago

        That one person who absolutely insists that enums are blue and everyone who can’t see it is a failure of a programmer

    • philipov 3 months ago

      I had never considered that, but you're absolutely right. I would totally be the sort of person to manually idiosyncratically syntax highlight my code if it were feasible. I'm sure glad I don't feel compelled to do that...

      • masklinn 3 months ago

        An other option is to have the color be semantically significant in which case you can't idiosyncratically syntax highlight. That's what colorForth does. It's weird.

    • zzo38computer 3 months ago

      Some programming languages such as ColorForth require colours in order to work, that the meaning of a word depends on what colour it is written with.

  • arp242 3 months ago

    There's always someone who mentions this, and it just doesn't work.

    Do you group things like:

      do_stuff()
      more_stuff()
    
      other_stuff()
      moar_function()
    
    Or:

      do_stuff()
      more_stuff()
      other_stuff()
      moar_function()
    
    Or:

      do_stuff()
      more_stuff()
      other_stuff()
    
      moar_function()
    
    Grouping code by a single blank line can make a big difference. This is a bit of a silly example, but there's tons of not-so-silly examples. You can't really represent that in an AST.

    Line length is another. infinite line length doesn't work as screens aren't infinitely long. Automatic wrapping doesn't work because you want to break at specific points. An example is something like:

      window = XCreateWindow(display, XRootWindow(display, screen),
          center_x, center_y, size, size,
          4,              // border width
          vinfo.depth,
          CopyFromParent, // class
          vinfo.visual,
          CWColormap | CWBorderPixel | CWBackPixel | CWOverrideRedirect,
          &window_attr);
    
    Cramming as much as possible on as few lines as possible is just not going to work well.

    There's tons of cases.

    That's why no one does it. Because it just won't work. Everyone will hate it.

    • wruza 3 months ago

      Grouping code … You can't really represent that in an AST.

      <visual-group>…</visual-group>

      Also, I wish that at least in current editors there would be a way to render \n\n as a half-height line. Full-height empty lines are too bold.

      Automatic wrapping doesn't work because you want to break at specific points

      You really want to have a set of buttons that switch between:

        - a line of arguments
        - a block of arguments
        - a line/block of only non-default valued arguments
        - arguments sorted by name
        - …
      
      And a hint on a default representation, with some default heuristics.

      How does it know that x, y, width, and height are semantically grouped and best put on the same line? It doesn't. (from the other comment)

      Look higher, parameters can be grouped at the declaration level. <params><related-params name=“coords”>…</>…</>. Now you can render a nice frame around these in block mode. Or not, depending on local renderer settings.

      Everyone will hate it.

      There’s always a way to make everyone hate something, especially if the solution is clueless about its problem. It doesn’t mean it should be done this way. Experiment and evolution could make it work, we just have to let people try instead of dismissing it so confidently.

    • otteromkram 3 months ago

      I agree about horizontal space adding to readability and I use that method fairly often.

      That said, if you use classes, descriptive names, and appropriate comments, it won't matter how you group because your code will be self explanatory.

      Finally, with today's wide-screen monitors on desktop, line length is less of a worry. Problem only arises when reading code on mobile devices.

      The last workplace I was at had a soft wrap around 80 characters, but we upped that to 100 when functions and methods became almost vertical.

      • layer8 3 months ago

        Line length is a worry because of readability. This is unrelated to the width of monitors. Having to read and visually parse a 200-character line is no fun. In addition, since most lines are relatively short, you also don’t want to have your source code window extra wide just in case, if instead you can use that space for other useful information and controls.

        Also, why does your comment have a paragraph break after each sentence except after the third? Because of semantics and the related readability. The same is true for source code. Readable layout does not depend on syntactical structure alone.

      • antifa 3 months ago

        > today's wide-screen monitors on desktop, line length is less of a worry

        did you buy a large monitor just to full-screen a single text file?

      • arp242 3 months ago

        You want to wrap in logical locations at times. That's my point. To repeat: cramming as much as possible on as few lines as possible is just not going to work well. Wrapping at column 80 vs 100 or whatever has nothing to do with that. That XCreateWindow() would be:

          window = XCreateWindow(display, XRootWindow(display, screen), center_x, center_y, size, size,
              4, vinfo.depth, CopyFromParent, vinfo.visual, CWColormap|CWBorderPixel|CWBackPixel|
              CWOverrideRedirect, &window_attr);
        
        And that's just not better. It's much much worse. Only a human can judge where it makes sense to break things (or not break things).

        Completely forbidding "paragraphs" would be atrocious. Almost everyone will hate it. Just like everyone hates walls of text in comments.

        And in the end a huge amount of complexity is added throughout the entire stack (from editors to grep to sed to code hosting) for very marginal gain with significant trade-offs.

    • svieira 3 months ago

      Two points:

      1. Breaking at specific points is something that can be specified by the pretty-printer of the _viewer_ you are using. Think of existing auto-formatters and imagine that they're working over the view instead of the persisted form.

      2. The AST can have pointers into advisory data (or the other way around, if desired, the "program data" can include the AST, but also other things as well) to note that there is an anonymous region here (C# and friends already have conventions for this _for the source code_ that Visual Studios understands - look at `#region` comments). This would let viewers choose their preferred representation for a region.

      • arp242 3 months ago

        You can't specify it in the viewer, because it won't know where to break. How does it know that x, y, width, and height are semantically grouped and best put on the same line? It doesn't. Auto-formatters can't format this. Or rather: they can only format it in dumb ways.

        And including tons of extra info in the AST means you've just got the same as a text file, but in a more awkward and obfuscated format.

        Also what you want can already be done right now. Converting your source code to AST and then formatting it how you want is already easy to do. But your coworkers will hate you, because you will lose all these small details that are actually quite significant. And there is no way to get them back once they're lost, so your coworkers all using some formatting tool is not going to help.

        • svieira 3 months ago

          You're thinking about the AST as the-AST-for-LanguageX not the-AST-for-LanguageX-withAdvice. Including an AST node called `Region` or a decoration for "Region" that multiple AST nodes can point to (or vice-versa a list-of-region indicies pointing into the AST tree) _that is serialized and stored in the same kind of way that #region is for C# code_ would allow for multiple people to look at the code structured in the correct way while displaying that structure in different ways (color coding vs. block outlining vs. extra newlines vs ... you get the idea).

  • foolswisdom 3 months ago

    Well, a few days ago there was a post about the Unison language, where code is stored in AST form and text is just a representation.

    https://news.ycombinator.com/item?id=40882133

    • KMag 3 months ago

      I've long dreamt of a system that compiles to native code, but stores a compressed SSA form (similar to SafeTSA or LLVM bitcode) in the binary for efficient runtime re-optimization based on profiling, somewhat similar to current Android Runtimes. One could then have several levels of debugging symbols, one that gives names to local variables represented by CFG nodes, and another that adds a compressed diff between some standardized decompiler output and the original source.

      You could then decompile to some alternative syntax, but you'd lose any idiosyncratic formatting represented by the compressed diff.

      • zeusk 3 months ago

        You mean Java or .NET?

        • KMag 3 months ago

          I'm not aware how to get byte-for-byte identical source out of a Java class file or .NET assembly.

          Last I checked, Java AoT compilation precluded runtime re-optimization, though I presume they've fixed that by now.

          Last I checked, they both used stack-based bytecode, which typically takes longer to JIT and results in slower native code than a compressed SSA / control flow graph (see the SafeTSA papers).

      • neonsunset 3 months ago

        .NET assemblies are that :)

        Though SSA is deferred to JIT/ILC instead. In either case you get the access to all the actual low-level bits when you need to. No other portable target lets you do that.

        • KMag 3 months ago

          If you add an extra blank line, or add a trailing space to a line, can you really get that back out from a .NET assembly? Normal disassembly at a minimum results in a loss of formatting.

    • __MatrixMan__ 3 months ago

      Last time I looked, [Unison code] -> [entry in the AST DB] was a one-way process. Adding a function means writing it (with whatever style you like) and seeing if what you wrote constitutes a new function or an existing one. You can't fluff db entries back up in to human friendly code.

      I don't see why it couldn't be done though, I think it just hasn't been a priority. Heck, you could have 100 different users collaborating in 100 different "languages", and so long as they serialized to the same AST and back, none of them would ever have to see the atrocious syntax which the other users prefer. Their editors and browsers could just render everything according to their users' preferences.

      Edit: it appears that Unison has an issue for this feature: https://github.com/unisonweb/unison/issues/499

      • tkzed49 3 months ago

        if they were truly represented by the same AST, I can't believe the differences between these "languages" would be anything more than swapping symbols out.

        • __MatrixMan__ 3 months ago

          True. Perhaps "styles" or "syntaxes" would be better. It's all that stuff we spend time building consensus around, but that doesn't affect program behavior. If our tools respected our style preferences on a user-by-user basis, we could drop the consensus requirement altogether.

  • Varriount 3 months ago

    I can understand braces (to an extent...). What really confuses me are new languages that still require semicolons at the end of expressions/statements.

    • TwentyPosts 3 months ago

      Speaking from a Rust-perspective, having semicolons at the end of statements makes perfect sense and is a brilliant design decision.

      Note that I said 'statements', not 'expressions'.

      A lot of the confusion here (and maybe yours, too) stems from this difference. In Rust, (almost) everything is an expression by default, and you turn it into a statement by adding a semicolon. This allows you (and the type checker) to very neatly distinguish between expressions and statements, which is great. It's a very nice and elegant approach imo.

      • Varriount 3 months ago

        Yes, but: - Is having everything be an expression by default a good design choice? A not uncommon idea in programming language design is that certain language constructs (for example, variable assignments) are better off as only statements, as their potential for confusion outweighs their usefulness. - Why should the burden of additional syntax be placed on the most common scenario? Statements (or the desire for statement-like behavior) tend to be far more common than lone expressions. Why not require lone expressions to be specially marked, rather than statements? - Do the benefits of this approach outweigh its costs? Is elegance a desirable trait, and what is its importance relative to other values, such as clarity (how accurately and easily is the writer's intention conveyed to readers) and user experience (what is the potential for this syntax to be forgotten or misused).

        Personally, I much prefer the design Go uses (where semicolons are implicitly added at the end of newlines following an identifier, numeric or string literal, keyword, or operator).

      • Spivak 3 months ago

        Does the difference ever come up in a meaningful way? Is there a syntax that without the trailing semicolon is ambiguous between the two, and the difference changes the behavior?

        • jihiggins 3 months ago

              let x = {
                  3
              };
              let y = {
                  3;
              };
              assert_eq!(x, 3);
              assert_eq!(y, ());
          
          i think it'd also mean having to parse whitespace or newlines without something like that?
          • Spivak 3 months ago

            Thanks, I hate it. Is there any time where you want to use this? Like if Rust worked like other languages and just figured out if it was an expression or statement are there times where you would need an override?

            I'm playing around with this in the compiler explorer and I'm now even more confused why you want this.

               let x = {
                 println!("Don't mind me in the struct definition");
                 3
               }
               assert_eq!(x, 3);
            • steveklabnik 3 months ago

              One of the things going on here is consistency.

              It's not so much that this ability is specifically put in for some reason. It's just something that falls out of several other things.

              Rust chose a "curly braces and semicolons" syntax because that's the sort of syntax that is normal in the sorts of PL spaces Rust wants to be used in. I am not sure exactly why being expression-oriented was chosen, but if I had to guess, it would be due to that just generally being considered a better option among many people at the time it was chosen.

              So okay, you want expressions, and you want semicolons. Therefore, "you separate expressions with semicolons" is a pretty natural outcome. And since we're expression oriented, "a block is an expression that evaluates to the final value" is near tautological. And since it's an expression, it can go anywhere an expression can go.

              Not being able to do this would mean creating specific restrictions against it, and then having to memorize when things don't follow the usual rules. That's more complicated than just letting expressions be expressions.

              (also your let is missing a semicolon)

            • masklinn 3 months ago

              > I'm playing around with this in the compiler explorer and I'm now even more confused why you want this.

              It works with RAII to create a temporally isolated resource scope, think context managers / using / try-with-resource; it provides a scratch space where you limit collisions with the rest of the function and avoid the risk of mis-reuse of those values; and before non-lexical lifetimes it was critical to limit borrow durations. It's also routinely used in combination with closures, to prepare their capture. Similar to C++ capture clauses, but without special syntax.

              It's essentially a micro-namespace inside the function.

            • mplanchard 3 months ago

              This kind of thing is useful for memory management. Anything you allocate within the scope that isn't returned gets dropped at the end.

              You can use this to e.g. acquire a Mutex guard, move/clone something out of the mutex, and ensure it gets dropped as quickly as possible.

                  let x = {
                      let items = vec![1, 2, 3];
                      items[1] // copied out of the vec since usize implements the Copy trait
                      // compiler inserts drop(items) here
                  };
                  // items is no longer valid
                  assert_eq!(2, x);
              
              It also comes up in if/else blocks, which have exactly the same syntax and semantics (i.e. they are expressions, not statements):

                  let condition = true;
                  let x = if condition {
                      println!("condition is true");
                      5
                  } else {
                      println!("condition is false");
                      10
                  };
                  assert_eq!(5, x);
              
              edit: and of course, function blocks work exactly the same way! It's neat.
            • jihiggins 3 months ago

              idk there are a lot of uses for it

                  let dx = {
                      let prev_x = x;
                      x = get_x();
                      x - prev_x
                  };
              
              often, it's slightly better cpp style scoping blocks if nothing else? there are tons of other little QoL things it enables though, but they're all going to be little ergonomics things that only seem worth it if you've used the language for awhile
              • masklinn 3 months ago

                Also common to set up "capture clauses" for lambdas as Rust does not have that in the language, IME most common with threads:

                    spawn({
                        let a = a.clone();
                        let b = &b;
                        move || {
                            // do something with the a you cloned and the b you borrowed
                        }
                    })
        • masklinn 3 months ago

          All the time. A block (in the general sense so that includes function) which ends with an expression will have that expression’s value as its own value (/ return). A `;` converts the trailing expression into a statement, which does not have a value, and thus the block returns `()` (the something representing nothing).

          Method chaining is also common in Rust, because builders are common, and chains of iterator adapters are common, and chains on monadic structures (option/result) are common, … having every line break implicitly insert a `;` would be horrid.

          • notpushkin 3 months ago

            Wait, so this is legal:

                fn five() -> i32 {
                    5
                }
            
            and this isn't?

                fn five() -> i32 {
                    5;
                }
            
            I can't tell if I'm amazed or terrified.
            • jihiggins 3 months ago

              this is what those end up being, it's pretty straightforward?

                  fn five() -> i32 {
                      return 5;
                  }
              
                  fn five() -> i32 {
                      5;
                      return ();
                  }
              
              semicolon changes the expression from returning the result of the expression to running the expression and returning the unit type. if you accidentally do that and specified a non-unit-return-type in the function signature, the type checker tells you about it:

                  error[E0308]: mismatched types
                   --> src/main.rs:1:14
                    |
                  1 | fn test() -> i32 {
                    |    ----      ^^^ expected `i32`, found `()`
                    |    |
                    |    implicitly returns `()` as its body has no tail or `return` expression
                  2 |     5;
                    |      - help: remove this semicolon to return this value
              
              which is also pretty clear about the solution
            • masklinn 3 months ago

              Yes.

              > I can't tell if I'm amazed or terrified.

              The rule is very simple and obvious, and the compiler will yell at you if you get it wrong.

              It's also very useful and even critical of how expression-oriented the language is: an `if/else` or a match statement must typecheck, all branches have to have the same type. It's obvious if you're using it as an expression, but it doesn't go away if you're using it for the side-effect (as an imperative conditional/switch) and then things can get more dicey as the expressions in each branch can have different types. `;` solves that by making every branch `()`-valued.

              • notpushkin 3 months ago

                Okay, this is really neat design. I went to check whether if..else works in an expression context and it does:

                    fn five() -> i32 {
                        let a = if (true) { 3 } else { 6 };
                        return a + 2;
                    }
                
                Pure fun!
                • masklinn 3 months ago

                  Ya if you want fun match/case also works like that.

                  And though for abs while don’t (they always return ()) `loop` itself does, you can `break` with a value and that’s what comes out the loop.

    • stkdump 3 months ago

      What confuses me is languages that can split statements over multiple lines as long as certain conditions are met (such as the break occours inside braces). I rather have a semicolon at the end of the statement to make it more explicit.

      • RHSeeger 3 months ago

        This is where I stand. Semicolons convey intent, much like parens in math equations. Sure, the code makes it clear (if you understand the rules) what "the code does", but having semicolons (and parens) make it clear that "what the code does" and "what the writer intended the code to do" are the same thing.

        Plus I don't think I've ever seen a case where semicolons made the code harder to read (or write).

      • xigoi 3 months ago

        But why a semicolon? Sentences have been terminated by periods for hundreds of years until programmers decided to be special snowflakes.

    • voidUpdate 3 months ago

      I like semicolons, because it lets me use the brackets style I prefer (allman) instead of whatever the language devs think I should use. This is a really big issue for me trying to use Go, as they automatically insert a semicolon to the end of every line that doesn't end with a {, so the language forces you to use K&R, which I really dislike reading

      • xandrius 3 months ago

        That's not really true though, I've used golang for years and never had semicolons added automatically.

        • arp242 3 months ago

          The Go compiler inserts semi-colons. https://go.dev/ref/spec#Semicolons

          If you follow those rules, you will see that this:

            if true;
            {
                fmt.Println()
            }
            else
            {
                fmt.Println()
            }
          
          Will get rewritten to:

            if true;
            {
                fmt.Println();
            };
            else;
            {
                fmt.Println();
            };
          
          And that won't work. That's why the braces need to be as "} else {". and "if .. {".

          It used to be that the compiler gave some pretty confusing errors about semi-colons on this, but it seems that's been improved now.

          JavaScript has similar semi-colon insertion by the way, but with some different (more confusing) rules.

          • xandrius 3 months ago

            That's really neat, it had escaped me till now. Thanks for the explanation (today I'm one of the lucky 10,000!)

        • voidUpdate 3 months ago

          I don't mean it actually adds them to the file itself, its like it adds virtual ones during compilation. Try placing the { from the func main() { on a new line and it will fail to compile

          • xandrius 3 months ago

            Oh, I see, that's what you meant. Thanks for clarifying :)

    • layer8 3 months ago

      In general, what helps parsers for disambiguation also tends to help human readers for disambiguation. In addition, some amount of redundancy helps to prevent errors when (for example) two statements were intended but they are parsed as one, or vice versa. Furthermore, consistency helps avoid errors, such as always ending a statement with a semicolon and not only when it would otherwise be ambiguous.

    • IcyWindows 3 months ago

      Why is that so much more different from requiring '\n' instead of ';'?

      • sodapopcan 3 months ago

        Because when reading as a human you're typing `\n` anyway which fits in with the whole "Can't the computer just figure out what I'm seeing?" thing. While it's technically correct (the best kind of correct) that it's '\n' vs ';', in practice it's really ';' vs ';\n'. I can only speak to my personal experience but seeing two expression on one line is so rare that I can't even think of an example of the last time I saw it.

        • masklinn 3 months ago

          The problem is not two expressions on one line, it’s one expression on two lines. e.g.

              foo
                  .bar()
          
          now you need to either add syntax to specify that you’re “continuing” (python), play tricks for the parser (Go), or have unreliable magic biting you in the ass half the time (javascript).
          • arp242 3 months ago

            It's not that difficult; just place the "." at the end of the line:

              foo.
                bar()
            
            And that will work fine. At least in Go.

            You can endlessly argue what location is better for the ".", but it really doesn't really matter. Regardless, you don't really need to do parser tricks.

            • masklinn 3 months ago

              That's exactly what I mean by parser trick. You're relying on the idea that if the parser sees an incomplete expression it won't end the statement then and there.

              It also looks like shit, because now you have to check the end of the previous line to know whether it's a method call or a function call which was indented in incorrectly.

              • sodapopcan 3 months ago

                Sure but that doesn't quite answer my question: is the parser trick really that bad?

                I do see what you mean, of course, and am aware of the arguments but I've never found lack of non-whitespace expression terminator even remotely confusing. I can clearly see indentation in my periphery signalling that it's multi-line. I can also say that in ~13 of using exclusively using semicolon-less languages, I've never had or even heard of a problem caused by someone misunderstanding where an expression ends.

                Anyway, this is getting pretty bikesheddy, lol but ya, to each their own, obviously.

              • arp242 3 months ago

                With gofmt it's always indented correctly.

          • sodapopcan 3 months ago

            I understand it's likely stupid in Python since it's whitespace significant, but are those Go parser tricks really such a big deal or even very tricky?

      • gavindean90 3 months ago

        Maybe I like the ‘\n’ for me and the ‘;’ for the compiler.

        • xigoi 3 months ago

          There should be only one source of truth.

  • smsm42 3 months ago

    Non-human-readable primary representation may be not the best idea though. Would create a lot of friction when trying to process the data. Text is largely simple and obvious (yes I know there are complications but in 99% of cases you can ignore them without too much trouble) but DBs and ASTs are not. People read texts, but they can't read ASTs, at least not without assistance. So it'd be hard to use.

    • skissane 3 months ago

      > Non-human-readable primary representation may be not the best idea though.

      What if the AST is persisted as S-expressions, but then you have a different syntax to edit it? Algol-ish, Pascal-ish, C-ish, Python-ish: choose your poison (or even support multiple poisons and let the developer pick the one they prefer?)

      This was actually the original plan with Lisp. Lisp was originally supposed to have two syntaxes, S-expressions and M-expressions, with M-expressions being Algol-like. However, the implementation of M-expressions was delayed, and people got so used to using S-expressions directly, they decided M-expressions were unnecessary and they were never implemented in mainstream Lisp. They were implemented in the Lisp 2 project, but that ended up being an evolutionary dead-end; various attempts at the idea have happened since but none of them really took off.

      Lisp purists will argue M-expressions are unnecessary and S-expressions are all you need. However, S-expressions can make the language more foreboding to complete beginners, and even among experienced programmers, a decent percentage find them seriously off-putting. Maybe if the M-expression idea had been pursued more seriously, Lisp might be more popular today.

      • lispm 3 months ago

        > Lisp purists will argue M-expressions are unnecessary and S-expressions are all you need.

        I would argue that S-Expressions turned out to be extremely practical for developing Lisp software. A layer with different syntax makes it more complex to use.

        > Maybe if the M-expression idea had been pursued more seriously, Lisp might be more popular today.

        Maybe, maybe not. People have discussed it endlessly, but there is no conclusion.

        Currently some people in the Racket community try to make Racket more "popular" (widely used, ...) by providing a new syntax.

        • perrygeo 3 months ago

          Not just practical, S-Expressions are a big part of Lisp's superpowers from a UI perspective. You can manipulate code as forms, not text. It's hard to overstate how much of an advantage that brings to a well-configured editor.

          When you start thinking of your program as a nested data structure instead of a text document, you start thinking more clearly - you can manipulate this tree representation directly. This makes molding your program significantly faster, closer to the speed of thought. Wholesale refactoring a function might only take a dozen keystrokes to move the forms (not the chars) around.

          I have a hard time going back to the syntactic busywork of manually placing ascii characters like a caveman.

      • smsm42 3 months ago

        S-exp is an interesting idea. Technically they are human readable, and certainly would be processable by text tools, with some effort. Lisp maps to S-exps very well obviously but I wonder if the same amount of synergy can be achieved in the language that is not aimed at that at the start, or it will just become a binary dump with extra steps instead. Definitely would be interesting for somebody to try.

        • masklinn 3 months ago

          > Lisp maps to S-exps very well obviously but I wonder if the same amount of synergy can be achieved in the language that is not aimed at that at the start

          But lisp did not aim for that from the start, as the GP hinted McCarthy intended S-expressions as a data description form, m-expressions were supposed to be the executable language.

    • maccard 3 months ago

      It’s all still bytes under the hood, albeit standard bytes. Personally I’ve not found the ability to open my css files in Word beneficial!

      Many editors are already altering what is stored on disc before presenting it to you - type annotations, code folding, git info. I think we could do a lot if our default storage was the semantic representation of the code.

      • smsm42 3 months ago

        > Personally I’ve not found the ability to open my css files in Word beneficial!

        Imagine writing a blog about your favorite CSS features. I mean, if you use Word at all for writing, wouldn't that come handy?

        But Word actually is not the primary goal here. grep or awk may be more important - I've created ad-hoc tools for ad-hoc quick-and-dirty tasks on code a number of times, and the fact that code is just text helped a lot. Taking that away would make me spend time on figuring out how to hook up text tools to that format.

        > Many editors are already altering what is stored on disc before presenting it to you

        True, but the difference is between being able to enrich commonly understood format, and not having a common format between different tools at all.

        • maccard 3 months ago

          Yeah, I was definitely kidding when I was referring to Word.

          I do feel sad that we're still restricted to tools like grep and awk that treat everything as dumb text, and I think it holds us back hugely. I much prefer the powershell model of everything is an object. You can easily extend it with C#.

          I appreciate that the unix philosophy has gotten us to incredible places, but I do wish we could rip off some of the training wheels and take advantage of the computing power that we have available to us that was just unthinkable. My mobile phone is more powerful than could possibly have been imagined when we make restricted itself to tab as a delimiter, and I'm currently using it as a coaster to save my table from water marks.

          • smsm42 3 months ago

            The problem of powershell model it's a closed system. If it does X, it's awesome. If it doesn't X, but there's a tool that does X and doesn't speak the same language powershell speaks - you are out of luck. That's where simple exchange formats win - they can combine tools from different domains. If I have a system that can do X using SuperDuperObjectProtocol and then another one doing Y which uses EvenBetterDifferentObjectProtocol - doing X+Y is a project that could take months if not years. If they both input and output some common easy format - like text or JSON or CSV - I can likely hooks them up in a lazy afternoon. It's not the question of processing power - all the super-comupters in the world would not make the task of hooking up SuperDuperObjectProtocol with EvenBetterDifferentObjectProtocol easier. It's the question of complexity, which always appears on the edges of domains.

            • maccard 3 months ago

              I think that falling back to the lowest common denominator is an immense cause of complexity in software, and holds us back back. I think we'd be much better off if we didn't optimise for "person who wants to write a CLI in haskell who is using an 18 year old version of bash that only runs on Plan9"

  • bsza 3 months ago

    So much opportunity for anti-competitive behaviour. The "canonical representation" of C# could just be a memory dump of Visual Studio. Your code is held hostage forever. Everything you create belongs to Microsoft. You have to drink a verification can to keep using your IDE. Basically Unity/Adobe/etc, but for code. No thanks.

    • neonsunset 3 months ago

      https://github.com/dotnet/dotnet there, the entire source code of runtime, sdk, roslyn, etc.

      And you will have easier time getting your changes merged into dotnet/runtime than into Python.

      • bsza 3 months ago

        You do realize I'm talking about the OP's alternative reality, not ours?

        • neonsunset 3 months ago

          It's HN, so the sarcasm above is often expressed seriously, as unfortunate as it is. You are right, of course.

  • quasarj 3 months ago

    You just described a literal nightmare D:

  • signaru 3 months ago

    Maybe no longer true today, but with the right tools, C# and VB.NET used to be auto translatable from each other and IL can be decompiled to either.

    • hermitdev 3 months ago

      It was only ever true for "clr safe" code, or a subset of C#. In particular, since VB.NET didn't/doesn't have unsigned types, not all C# could be expressed in VB.NET, even after decompiling from IL. (Not sure what happens if you try and decompile to VB.NET code that uses unsigned, for example).

  • Vegenoid 3 months ago

    Seems like the biggest downside would be that sharing code becomes much harder. Currently it is easy to share code in as small of a portion as you'd like. If the canonical representation is an AST, it opens up a lot of problems around sharing pieces of a program. This seems like a very substantial downside.

    Even simply "sharing" within your own systems, like copying blocks into notes or another program, would be a lot harder. Maybe I'm not knowledgeable enough here and this wouldn't be as thorny as it seems.

    • hombre_fatal 3 months ago

      Also, I really don't want to have to load any and all code into a local editor just to view it and reason about it.

  • eiffel31 3 months ago

    You can (sort of) do all of that with the Eclipse Modeling Framework[0].

    Your AST is what EMF calls a "model". By default the "backend" and ecosystem surrounding EMF is skewed towards Java for historical reasons, but there have been some prototypes with other languages as well. You can serialize your AST in any way you like, although by default it relies on XMI files. You can implement your own textual concrete syntax, or rely on a database. The EMF ecosystem has tools for implementing textual or "graphical" concrete syntaxes. You can combine them (e.g. usually a specific subset of your AST gets edited in a certain way that's best for your targetted end users). The ecosystem also has tools for performing comparisons and plugging them into your editing means.

    Of course all of this tooling requires a lot more work than an LSP server.

    [0]: https://eclipse.dev/modeling/emf/

  • crabbone 3 months ago

    I believe, this was an idea in ALGOL, not sure which iteration.

    I think, the reason it was never implemented was that more translation = more complicated debugging. It also means that programmers have a more distorted and incomplete model of the program they are writing, i.e. more bugs.

    NB. Lisp, as originally envisioned by McCarthy, had one more translation layer (the translated version had square brackets instead of the parenthesis), but it didn't take off for, basically, the same reason.

    So... while I understand the benefits you see from doing what you suggest, I think that at the same time the downside makes this not worth pursuing.

  • LeFantome 3 months ago

    In the .NET universe, you can mechanically convert between C# and VisualBasic. This is more or less done by going through CIL ( Common Intermediate Language - .NET assembly essentially ). So, it is more or less what you are saying.

    .NET decompilers are common. I have built a few toy languages and compilers on .NET. For one of them, I could decompile CIL into my language. So, I could view .NET libraries from other sources in my language.

    I think this is essentially the same idea you are proposing.

    It only works if the languages are similar though. Going between F# and C# does not always work as well for example.

  • heresie-dabord 3 months ago

    > you could configure the syntax however you wanted. And sure, it would be persisted to disk in some canonical representation, maybe text, maybe a DB ... but you'd never need to worry about it, because all your tooling (VCS, diffs, refactoring tools, etc) would work with the AST, and you'd never need to worry about tabs or spaces ever again.

    You are describing an entire industry of IDE Smell with an IDE monoculture.

  • turndown 3 months ago

    Programs are tightly coupled to textual representations because a compiler is a textual representation transformer. If you deviate from the accepted textual form then the compiler is generally clueless to do anything - that is, it can’t read your intent.

  • hsbauauvhabzb 3 months ago

    First we gotta solve the tabs/spaces dilemma, maybe then we can start to tackle the rest.

    Edit: I do agree and find your AST suggestion profound though!

    • layer8 3 months ago

      People should recognize that tabs vs. spaces is more a question of editing (e.g.: What happens when you press Backspace behind an indentation? Does the caret move at uniform speed on key repeat or does it suddenly jump in places?) than of stored representation. You could even have an editor/viewer that lets you choose the display-width of spaces at the start of lines.

      • hsbauauvhabzb 3 months ago

        Do tab users not realise they could configure their editor to auto-indent and delete multiple characters so they could move to the most superior spaces format?

        • layer8 3 months ago

          I don’t know of an editor who can fully emulate Tab behavior using a spaces representation (and vice versa), but it would certainly be possible.

    • moonlion_eth 3 months ago

      There are tabs people and there are infidels

      • pantulis 3 months ago

        I was ready to throw some vitriol into your heretical comment and then I remembered I am also a tab person. Nothing to see here, sorry!

        • hsbauauvhabzb 3 months ago

          I mean my original comment was highlighting that it’s unsolved and it instantly started infighting so I think my point has been proven

  • TOGoS 3 months ago

    This is what Unison is supposed to do. As far as I know there is currently only one (Haskell-like) textual representation, but the program is stored in a binary representation of the AST, and once you've entered your code, it's all operations on that AST from then on, and adding different frontends should be not difficult.

  • griftrejection 3 months ago

    Code is linked to textual representations because code... is text? The entire point is that there are algorithms to go from "print()" to something that actually makes the computer work. How else could it even possibly work?

    I think we don't have any sort of flexible AST sort of thing because they're mostly not necessary. The hard problems of programming don't usually have much to do with syntax.

    And if you're going to downvote, kindly explain why, thanks. I just want to know exactly how this thing is supposed to work...

    • rgovostes 3 months ago

      The parent’s post describes how it could work.

      I may recall incorrectly but AppleScript may be an example: some file formats are serialized ASTs. The editor displays it as textual code. A downside of this is that you can’t save a syntactically invalid file.

      • josefx 3 months ago

        You could always have an AST node to encapsulate the invalid code. Of course any affected code would be stuck in the source format it was written in until it was fixed.

    • RHSeeger 3 months ago

      > code... is text

      There are visual programming languages that chain together blocks, instead of raw text.

      > The hard problems of programming don't usually have much to do with syntax.

      I guess it depends on how you define hard. You are clearly talking about "a singular issue that needs to be solved", which really only effects a single developer / team and, to a lesser extent, those that use that solution. But if you consider something like syntax, you're now talking about something that much a much smaller impact _per developer_, but has that impact on _every_ developer. The syntax issue may have a much larger impact overall.

  • rthnbgrredf 3 months ago

    Thanks to LLMs, we are quite close to achieving this. I can write code in Python (sometimes even plain english), and GPT can convert it to Go or even Haskell if I like. The conversion is accurate 95% of the time on the first attempt in my use cases, and I expect this to improve further with more powerful models in the near future.

    • lgas 3 months ago

      You can take it a step further, LLMs can already "execute" arbitrary non-existent languages, with non-existent data. Here are a couple of examples using a tool I wrote[1]:

          % echo "nums 1 10 | filter even | to_words | map uppercase" | refab imagine 
          TWO
          FOUR
          SIX
          EIGHT
          TEN
      
          % echo "with file '/tmp/top-ten-most-populous-cities.txt' do; cities = read; cities.each { |city| (city.name, city.utc_offset) }" | refab imagine
          Tokyo, 9
          Delhi, 5.5
          Shanghai, 8
          São Paulo, -3
          Mumbai, 5.5
          Mexico City, -6
          Beijing, 8
          Osaka, 9
          Cairo, 2
          New York, -5
          
      For what it's worth, the tool isn't specialized for this, 'imagine' is just one of many prompts it can execute.

      Of course the execution is non deterministic and at the moment only works for simple things, but you can imagine as LLMs get more capable and more integrated with tools this will matter less and less.

      [1] https://github.com/lgastako/refab

    • hsbauauvhabzb 3 months ago

      I hope we never work together. 95% accurate will cause problems that you won’t notice when you inevitably get lazy.

      • rthnbgrredf 3 months ago

        I'm a strong advocate for writing tests first, maintaining a robust QA process, and ensuring all merge requests undergo peer review. Since I started using GPT-4 for coding, the quality of my merge requests has remained the same. The difference is that I can now produce about twice as many merge requests, as GPT-4 handles the boilerplate writing, Stack Overflow searches and helps to start get going in case of a mental blockade or missing idea.

        • hsbauauvhabzb 3 months ago

          By what metric do you measure quality? Plenty of gpt users were dumping low qualify contributions prior to gpt, now their contributions are the same idiotic trash but appear more competent…

      • dotancohen 3 months ago

        This is how I feel about cars that can drive themselves 99.9% of the time. The remaining 0.1%, the most difficult of corner cases, are to be handled by the human who has no experience driving even in good conditions.

    • digging 3 months ago

      I largely agree, but I don't think the current experience is the right one.

      I recently started writing a game in Godot. I don't know GodotScript, and I've found I don't like it very much in trying to learn. I turned to aider.chat to see if I could describe the functions, data structures, and systems I wanted and have it write them. I also tried writing in a more familiar language (...one with braces...) and having it translate those files.

      It does pretty well, but it doesn't feel like software engineering. It's too hands-off and doesn't activate the same neurons. All the problem-solving and puzzle-solving is gone, and the successes are quite boring, and the failure modes are more irritating even if they're necessarily quicker to solve.

      It's a weird experience. I'm moving so, so much faster than I would have on my own, but I don't enjoy it. It feels like cheating - I'm not actually ashamed of what I'm doing but I also won't take credit for writing the code.

      However, what I'm getting at is this: If I could write the code in a syntax or even language that I prefer and have copilot or whatever translate it in near-real-time (without active prompting), that would be the best of both worlds. I'd still be a little sad at myself if I didn't learn the new language, but I also think this method would facilitate learning better than what I'm doing with aider (because I could see what my code turns into as I'm writing it, and learn that "translation").

    • 12_throw_away 3 months ago

      [flagged]

      • rthnbgrredf 3 months ago

        I think it is not so much surprising that large language models are particularly good at languages, including programming languages.

    • randomtoast 3 months ago

      I can confirm that it is a suitable use case for GPTs. I do GPT-assisted programming language design and experimentation. In some cases, GPT-4 can even generate a basic interpreter that allows me to test my new language.

      Here is an example of GPT's output for Python with braces that was generated after just spending 10 seconds for the prompt:

        def preprocess_braces(code: str) -> str:
            lines = code.split('\n')
            processed_lines = []
            indent_level = 0
            indent_str = '    '  # 4 spaces for indentation
      
            for line in lines:
                stripped_line = line.strip()
              
                # Check for opening brace
                if stripped_line.endswith('{'):
                    processed_lines.append(indent_str * indent_level + stripped_line[:-1].strip() + ':')
                    indent_level += 1
                # Check for closing brace
                elif stripped_line == '}':
                    indent_level -= 1
                else:
                    processed_lines.append(indent_str * indent_level + stripped_line)
          
            return '\n'.join(processed_lines)
      
        # Example usage:
        code_with_braces = """
        def example_function() {
            if True {
                print("Hello, world!")
            }
            for i in range(5) {
                print(i)
            }
        }
        """
      
      
        processed_code = preprocess_braces(code_with_braces)
        exec(processed_code)  # This will execute the transformed Python code
      
        print("Processed Code:\n", processed_code)
      • im3w1l 3 months ago

        This code is incorrect though, as it doesn't account for braces in strings and comments. There are other issues too, but that is the big one.

        • AdieuToLogic 3 months ago

          > This code is incorrect though, as it doesn't account for ...

          Isn't this the fundamental problem with code generated by a statistical text generation algorithm?

          In other words, "code" is short for encoding a solution. And to have a solution to encode is to understand the problem to solve.

          Without understanding, statistical code generation is little more than a popularity contest.

          • roywiggins 3 months ago

            The model doesn't "understand" anything, but if you, the programmer, understands it well enough, that can be enough to direct it to find a solution.

            You can do a lot with ChatGPT or Claude if wrong code is easy to spot (which will obviously depend on what you're working on). If you can easily spot mistakes these things can often come up with a fix once you point it out. I've had some real success converting small-scale production C++ code into Python using Claude. Stuff that isn't really deep or complicated, but it's still faster and less annoying using an LLM to assist. I am sure there are large domains where it's crap, but for relatively simple stuff (CRUD logic, simple file parsing) it does remarkably well.

            • AdieuToLogic 3 months ago

              > The model doesn't "understand" anything, but if you, the programmer, understands it well enough, that can be enough to direct it to find a solution.

              This is exactly my point.

              Whether a programmer uses past experience exclusively to author source code or a statistical code generator (LLM) and then their learned ability is orthogonal to my original premise.

                Without understanding, statistical code generation is
                little more than a popularity contest.
          • im3w1l 3 months ago

            I disagree with everything you said.

            Code is not short for encoding a solution. Code is any kind of program whether correct or not.

            You can have a solution without understanding it. You can for instance know the rough shape a solution should have and try to guess at the details. And get it correct some of the time.

            And current models do have some form of understanding, although it is sometimes incomplete. They are clearly able to solve many problems after all.

        • skissane 3 months ago

          Just this morning I asked GPT-4o to write some code for me. And the code was correct, except for one stupid mistake GPT-4o made which caused a compilation error. I just fixed that myself, but I think it is likely if I gave GPT-4o the error message it could have fixed it too. And I was thinking if I set up a chain-of-thought agent with function-calling, GPT-4o probably could have discovered and fixed the compilation error itself without my involvement. Provide it with unit tests it may even get the code to pass the tests (even if it takes a few iterations)-which could address issues like the braces in strings and comments issue you mention, assuming the unit tests cover them. And if they don’t-if you notice an issue via code inspection or exploratory testing, GPT-4o (in my experience) often does a decent job of “here is the code and here is a description of the bug, modify the code to fix it”. Of course, sometimes chain-of-thought agents get stuck and fail to progress, but something that quickly gives you the right answer 80% of the time can be a big productivity boost.

          In my case earlier today, it helped that it was a relatively simple function and I gave it a rather detailed natural language spec of what I wanted it to do. I totally could have written it all myself, but writing a natural language spec and getting GPT-4o to translate it to code is (depending on my mood) less mental effort than just writing the code directly.

necovek 3 months ago

This is a great discussion with many a differing point of view.

To some, significant indentation is better.

Others — too used to braces — miss them dearly in Python.

Next ones, vie for the non-text source code, something to get us past these discussions altogether (editors working on .pyc files directly?).

For programs to be maintained, they need to be read, understood and improved. One—often undervalued—skill in programming is to write beautiful code, because that is more art than craft. And unfortunately, tools like Black prohibit the true artists from expressing themselves clearly with code formatting too. And to those, white-space or braces matters on a different level, and everything else is attempting to make up excuses for why one is better than other.

And while conceptual operations we do on the code seem simple on the surface, devising an editing tool that would do semantic operations on the AST is fricking hard and likely to be very non-ergonomic. Look at all the attempts to make code refactoring tooling: it's crazily complex and confusing that it's simpler to just go and grep for a string and fix anything you find.

As long as it's faster to use regular editing operations to shuffle code around, indent or unindent it (or wrap it with braces), tweak one thing here or there, simple text editors will mostly rule the world of programming.

  • kazinator 3 months ago

    Python encodes structure in only one way, using indentation. There is no redundant signal that can be checked for a discrepancy that could indicate a problem. GCC and Clang can diagnose when indentation is "misleading" because it doesn't match what the braces are saying.

    Python's choice of representation is such that two different Python programs show zero differences under a white-space-suppressed diff.

    The white-space suppressed diff is a useful tool for comparing programs when some sections of code have changed indentation but are otherwise the same; yet we cannot rely on it if we are using Python.

    Python's syntax design is objectively poor on several purely technical points. In its favor, there are only handwaving pop psych arguments.

    • xigoi 3 months ago

      > There is no redundant signal that can be checked for a discrepancy that could indicate a problem.

      What’s the problem with having no redundancy? By the same logic, we should require numerals to be spelled out in words so the compiler can check if the programmer didn’t accidentally write a different number.

        def fahrenheit_to_celsius(x): {
            return (x - 32 [thirty two]) * 5 [five] / 9 [nine];
        }
      • kazinator 3 months ago

        If we primarily relied on a whitespace representation of numbers, it would help to have digits there for the machine to look at and possibly diagnose against the whitespace.

        • necovek 3 months ago

          (Almost) Every programmer in the world depends on whitespace to understand code: are you claiming that's not true?

          If humans can do it, why wouldn't computer programs like interpreters do it?

      • kelipso 3 months ago

        Redundancy reduces likelihood of bugs. Your numbers example would too but it's obviously too much work for not enough benefit.

        • xigoi 3 months ago

          Braces are also too much work for not enough benefit.

          • necovek 3 months ago

            They are certainly more work and why I prefer significant whitespace, but I wouldn't really say "too much".

            They are a preference, but neither is objectively better or worse.

          • kelipso 3 months ago

            Given the chronic inconvenience of significant whitespace, absolutely not.

            • xigoi 3 months ago

              It’s thee braces that are inconvenient. I have to indent my code anyway, so why add another redundant marker that I’ll have to mentally filter out all the time?

            • necovek 3 months ago

              That's an opinion that is largely disproven by the amount of working Python code in the world.

              Why is it so hard to accept that this is your personal preference and is really not an "objective" statement?

              • kelipso 3 months ago

                The reason for the popularity of python is mainly due to advertising it to programming newbies and non-programmers, not due to significant whitespace.

                • necovek 3 months ago

                  I never brought popularity up: that mostly leads to lots of small snippets but not a big amount of working code. You can have an unpopular language with a few productive actors producing lots of code.

                  I argue that "chronic inconvenience" is disproven by so many working programs. Even if one argues it's an inconvenience, it is a minor one or it would be hard for non-newbies to produce so much with Python.

                  • kelipso 3 months ago

                    It’s a minor inconvenience, sure, I use python myself, but it’s definitely a chronic one. It annoys me every single time I code in python.

    • arcxi 3 months ago

      >The white-space suppressed diff is a useful tool for comparing programs when some sections of code have changed indentation but are otherwise the same; yet we cannot rely on it if we are using Python.

      yes, because in Python two programs with different indentation are not the same. what's the problem that you can't use tools intended for code without significant whitespace with code in Python?

    • necovek 3 months ago

      > Python encodes structure in only one way, using indentation. There is no redundant signal that can be checked for a discrepancy that could indicate a problem. GCC and Clang can diagnose when indentation is "misleading" because it doesn't match what the braces are saying.

      I've seen both misplaced braces (akin to mis-indenting blocks in Python), indentation not matching braces and other problems of the same sort in non-Python code. Readers of the code would misunderstand the code when badly indented, and might introduce bad braces as well (not everybody uses automatic formatters and linters either, esp as they will sometimes "quickly" edit code in their non-usual dev environment). Not to mention that some "braced" languages allow having single-line blocks without braces.

      It's also not true that this is the only way Python encodes structure: new blocks generally only start with a ":", and you've got control flow keywords that allow for new blocks to start. One could argue that's a great feature disallowing you from introducing confusing spacing without actually having a new block started.

      While I am fond of applying many of double-entry-accounting principles in programming to increase trust in what we write, I believe that's much better done with unit-tests, which can more clearly demonstrate the expectations for any code and read more like documentation.

      Do you think all syntax in programming languages should have some sort of extra validation built-in? Eg. you should type in a constant twice (declare it as `const int a = 5` and then you have to set the value later as `a = 5` or you get an error?)?

      As I said above, people will always find an "objective" excuse why their preference is better. But I've seen bad-block-boundaries in Python as much as I've seen it in other languages which use explicit block boundaries like braces (and I've done more Python over the last ~20 years). I've heard this argument a gazillion times, but hundreds of bugs due to that have simply failed to materialize while working on large projects with tens and hundreds of people.

      Getting indentation right is _really_ not that hard, just like getting braces right is not that hard. I've yet to find someone who prefers their code to not be indented at all, and only rely on braces — at least not in a team setting where you can't simply reformat all of it.

      • kazinator 3 months ago

        > But I've seen bad-block-boundaries in Python as much as I've seen it in other languages

        You have to consider ones you have not seen: the ones that are valid syntax, and thus invisible.

        > (declare it as `const int a = 5` and then you have to set the value later as `a = 5` or you get an error?)?

        For that, it would be more like assert (a == 5). It's not commonly done for constants. Neither the definition nor assertion are perturbed by significant whitespace, so it isn't the same.

        If the constant only exists for clarity and not configuration (so the code cannot conceivably work with any other value), then the assertion would be warranted:

          assert(a == 5); // Did you read the comment about not changing a?
        • necovek 3 months ago

          > You have to consider ones you have not seen: the ones that are valid syntax, and thus invisible.

          Sure, that's a fair point, but the same holds true for braces. One of those bugs I found in non-Python code was there for a couple of years (badly placed braces).

          For the other topic, you were specifically praising the duality of braces and indentation to understand block boundaries. It's hard to come up with an example where everyone does the non-obligatory thing anyways (indentation in {} languages), since obligatory thing is, well, obligatory.

      • zzo38computer 3 months ago

        I prefer using braces to delimit blocks (although the code will be indented, too), and semicolons to separate lines (the "automatic semicolon insertion" is, in my opinion, one of the worst features of JavaScript). Sometimes I will deliberately indent code in an unusual way, e.g. temporary debugging code might be not indented at all (although such things are not usually present in the final code; they will usually be quickly removed after being added, and such temporary debugging code is often are not committed to the version control system).

        The ability for GCC and Clang to diagnose misleading indentation can be helpful; some programmers may wish to use it (and others may prefer to disable it). However, apparently it treats a tab as a number of spaces; I think that it should not do that, and using tabs on some lines and spaces on other lines to measure indentation within the same block, should always be considered misleading indentation (so if -Wmisleading-indentation is enabled, then it should always display a warning message in that case).

        • kazinator 3 months ago

          That's a tricky requirement because some GNU programs do exactly that: use mixtures of tabs and spaces. For instance, the first three logical tabs are groups of 2 spaces, so 6 spaces. The fourth tab, however, turns into single hard tab.

          I think that to do this right, there would have to be a complex option in which you specify the tabbing style. -Widentation=<notation> where <notation> is some way of specifying the style.

          There has to be allowance for alignment also. Any line, regardless of indentation method, can terminate in one or more spaces that exist for aligning the fist non-whitespace character with something in the previous line.

        • necovek 3 months ago

          Do you deliberately "misindent" the code or is it mostly because it's hard to reindent and then back the change out? If the latter, that's obviously a different use case and one can use syntax tricks to achieve the same with Python if you don't want to have your editor help with that for whatever reason.

          • kazinator 3 months ago

            I also sometimes misindent some temporary debug print statements. However, indenting them right is just a matter of typing == in vim, while the cursor is somewhere on the misindented line.

            Moreover, the ] modifier before p or P (paste below or above current line) adjusts the paste to the indentation of that current line. It takes next to no effort to copy and paste some code to the correct indentation.

            Backing changes out nowadays is done with "git checkout --patch".

            • necovek 3 months ago

              Getting indentation right with editor support is trivial in Python too (in Emacs, TAB does what you describe anywhere on the line, and when there are multiple valid options, it cycles through those).

              Pasting blocks into right indentation or reindenting entire blocks too. So I am glad you agree it's simple to do any of these even with significant whitespace ;)

              I wouldn't know about other editors, but I'd be surprised if it's not so in every one of them.

              Where indentation really matters for temp debug statements — you want to enter a block unconditionally or skip it unconditionally — there are other syntactic tricks like add `True or`, `False and`, return, continue, break, semicolon, etc. But these are all temporary examples you are giving, and this only matters if editor is not supporting you.

              And that's my point: these are trivialities and I can't stop being perplexed that people get so fussy about it.

              I am not sure how git plays into this? It works exactly the same for Python, it's not like Python is bf with space as the control character.

          • zzo38computer 3 months ago

            Deliberately, both in order to mark it in a special way to stand out clearly, as well as to avoid having to add indentation for such a code where it is unnecessary and not helpful. That line of code will soon be deleted anyways, so it does not matter much if other people dislike it.

            • necovek 3 months ago

              Can you share an example where you non-temporarily add braces around a code block but then keep the indentation the same level as before the block? What do your collaborators think of it?

    • sverhagen 3 months ago

      > two different Python programs show zero differences under a white-space-suppressed diff.

      This must surely be a bad thing? How would this signal an unfortunate indentation change between:

        if foo:
          bar()
        bar2()
      
      And:

        if foo:
          bar()
          bar2()
      
      ???
    • thoutsnark 3 months ago

      I strongly agree with your main point that pythons syntax design is objectively poor, but content that even the grace you seek to extend to it is wrong

      >Python encodes structure in only one way, using indentation

      Except when you write a multiple line string using """ notation.

      Or when you put things inside parenthesis, which i have seen as the preferred solution for method chaining.

      Point is, python claims indentation is all that is needed, and then very quickly breaks it's own rule.

      • necovek 3 months ago

        Open parentheses and "multi-line" strings are simply Python's way to allow a single statement to span multiple lines in a nicer way: incomplete expressions continue across the newline (you can also do that with a common Unix way of escaping the newline — backslash right before you start the new line). FWIW, even """ notation does not require a string to be multi-line — it mostly allows using less escaping for things like newlines but also quotes.

        A preferred way to chain methods is to store values in descriptively named intermediate variables: it would also ease debugging as you'll get a direct pointer to the line that is problematic. Though, TBH, that's probably bad API design (I know it's common with DB query syntax, but that's attempting to turn SQL query construction into objects when they really aren't).

        Python, like most languages, doesn't really stop you from doing crazy stuff. But also like most languages, it can be done really well.

    • Too 3 months ago

      Most diff tools default to not suppressing leading whitespace. Trailing whitespace should be automatically removed and enforced by your code formatting tools, leaving no reason to suppress it.

      As someone who has been diffing endless amounts of python through various diff tools, this is totally a non issue.

  • mjevans 3 months ago

    go fmt is really nice, that there is A standard for the language which is just included. No more arguments, just do what the including tooling desires.

    Python... I'd love if it shipped with a formatter that converted indents to braces, and then had an option for expressing indent as spaces (with number of spaces per indent) OR tabs (same, default 1); then still kept the braces.

    • sigzero 3 months ago

      I really hate the "tab width = 8" though.

      • moonlion_eth 3 months ago

        There are kids out there with tab width 16 you should be grateful

        • winocm 3 months ago

          And there’s also people who use tabstops of 3.

      • arp242 3 months ago

        You can use a tabstop of 4, or 2, or whatever you want. It's not a problem. Don't need to use 8.

        • xigoi 3 months ago

          But the formatter will still line-break the code as if the tab width was 8, which will lead to lines with several lines of indentation being too short.

          • arp242 3 months ago

            When does that happen with gofmt?

  • duncan-donuts 3 months ago

    I think people are actually searching for Lisp far more than we are willing to admit.

darby_nine 3 months ago

I don't understand why we don't make the aesthetic aspects of syntax (e.g. block delimitation) to be a feature of the editor rather than the source of truth for the code. For all unix profited from text I think we have the tooling necessary to move our storage and editors beyond it, and it's been obvious the entire time it comes with non-trivial liability converting to and from more reliably structured representations.

  • williamdclt 3 months ago

    I think it boils down to “text is good _enough_” (80% of the value, 10% of the complexity if even that), and it’s a format that’s incredibly interoperable. You can use tools that aren’t just language agnostic, but are not even programming-specific: notepads, grep, git, sed…

    • darby_nine 3 months ago

      I agree completely; I just think on a gut-level a solution would be validated with use despite the small marginal gain over text in complexity of tooling. Among RAGs, TreeSitter, and the success of LSPs, I think there's room here to synthesize some improvements.

      While we're on the topic, if we store only syntactically valid programs, we can express diffs in terms of semantic refactoring rather than textual changes. This would enable stuff like preserving refactoring across merges, thereby bypassing conflicts that would arise under text merges. There are limits to this of course as you can still come up with conflicts, but anything to ameliorate the nightmare of manually fixing a textural merge.

      • digging 3 months ago

        Huh, your comment made me reconsider. Variable names are very important to code quality, so how would those be preserved if not using text? I suppose they could be programmatically generated to be "good" but I foresee illegible edge cases being frequent in that case.

  • cranium 3 months ago

    "Code-as-Text" is way too universal and deeply ingrained to change in the short to medium term. I've worked a bit with low code / no code platforms and everything becomes a mess: little to no version control, search is bad, no import or possibility to generate components programmatically,...

    However, I'm totally with you on having the editor show the code as you'd like. As much as I don't like tabs, at least the user could choose their preferred width for indentation. (A less disruptive Python-with-braces could be the editor showing braces but converting to spaces behind the scene.)

    • quectophoton 3 months ago

      > However, I'm totally with you on having the editor show the code as you'd like.

      Such editors would remove some categories bikeshedding, but would add brand new categories of bikeshedding.

      * Why did/didn't you add an empty line (EDIT: or whatever no-op visual equivalent) after that `if` block? My editor needs blocks to be separated a certain way to be able to display them nicely grouped in logical blocks! This representation of AST is so limited that we can't store such differences in style, we need editors that work at some super-AST level!

      * What do you mean my code is an unreadable mess with hundreds of operations? All I see in my editor is a nice single operation "copy fields from class X to struct Y". If your editor can't detect such an obvious thing from the AST and display it nicely, then find a better one.

      * Some codebases not even bothering with functions because the founding engineers use a specific IDE that just lets them group code arbitrarily (no no that's not reinventing functions, that's what progress looks like!), and you can't use your favorite editor because that's not on the scope of that editor, so the editor's author politely tells you to use that other editor you dislike if you really need such a thing.

      * I can probably come up with more scenarios if I spend more time thinking about it. And there's probably also more petty scenarios that I can't even imagine.

      I'm not saying such editors wouldn't be nice. Everyone has their own preferences, and some people might work better this way. Just, don't expect them to reduce the amount of petty bikeshedding in projects, much less eliminate it.

  • Nihilartikel 3 months ago

    I'm kind of with you here.

    Lispy languages have structural editing tools that make it a lot like working directly on an AST. It's a delight when you get used to it.

    The spacing/linebreaks are all just auto formatted and mostly an afterthought. It would only be one step further to present the code with the users choice of block start/end sequences.

    • darby_nine 3 months ago

      Working with paredit was certainly one of the main ingredients for structural editing (as opposed to textual editing) to click with me. I've been watching TreeSitter with great interest.

  • kevincox 3 months ago

    The freedom that text provides is not a blessing and a curse. Even small things like adding "paragraph break" lines in a run of code can make it more readable. Of course you can encode a limited number of these "style" features into your source AST but much like code formatters there is always a limit to helpful style that is preserved and irrelevant stuff that is rendered to each programmers preference.

  • islandert 3 months ago

    Would the JVM ecosystem almost be a working example of this? Since there are a variety of languages with editor integration that all compile down to the same byte code, it feels pretty close to what you’re describing.

    • kevincox 3 months ago

      I believe that JVM bytecode is too low level for a source format. At the very least you would need to preserve some form of comments. Also I think JVM locals lose their names during compilation.

    • darby_nine 3 months ago

      The JVM languages are pretty damn close!

    • kriiuuu 3 months ago

      Unison would fit here

  • quasarj 3 months ago

    You can have my plain text when you pry it from my cold dead fingers!

  • Gibbon1 3 months ago

    I think text based programming languages are a local minima that's it's hard climb out of. Partly because most languages aren't designed around being represented by structured data. And no one has any morden experience with that.

    But do imagine a world were changing the name of a field in a struct results in a single diff message, 'struct foo field bar changed to baz'. And where a change set to to a library can be mechanically applied to to code that depends on it and it just works.

  • voiper1 3 months ago

    Would VS Code support a plugin to _display_ python with brackets, but open/save to disk in standard indented format?

  • morkalork 3 months ago

    I always open these threads with the hope that someone will mention Fortress but so far I'm just disappointed.

DonHopkins 3 months ago

Python has always fully supported C style braces out of the box: you simply have to put a # before them:

    if foo == 1: # {
        print "one foo"
    # }
It also supports PASCAL style begin/end:

    if foo == 1: # begin
        print "one foo"
    # end
And it's fully internationalized, even supporting mixing multiple languages:

    if foo == 1: # beginnen
        print "one foo"
    # 終了
In fact, you can even mix styles:

    if foo == 1: # begin
        print "one foo"
    # }
Or optionally leave one of them out, or spell them any way you like, if you feel like it:

    if foo == 2:
        print "one foo"
    # fi
Even verbose COBOL style:

    if foo == 1: # perform conditional foo value check
        print("one foo")
    # end perform conditional
gary_0 3 months ago

Braces, maybe. But I've always felt that semicolons at the end of lines were just noise. I can tell it's the end of the line because it's the end of the line. The few cases of ambiguity that happen can be solved by common sense (in the programmer or in the parser).

  • nomel 3 months ago

    Semicolons are already supported in Python, for the cases where it might be needed (one liners on the command line), just not required.

        import sys; print(sys.executable)
        x = 5; # this is fine
  • darby_nine 3 months ago

    > But I've always felt that semicolons at the end of lines were just noise.

    I felt this way until I engaged in code with very horizontal coding styles. Semicolons make it extremely easy to visually break up sequential statements from expressions consuming multiple lines.

    • gary_0 3 months ago

      > code with very horizontal coding styles

      I'm not sure what you mean. Could you give an example?

      • darby_nine 3 months ago

        Literally just code with long lines. You run into this particularly with monadic stuff like LINQ queries.

        • gary_0 3 months ago

          I grepped up some old LINQ code I wrote (sanitized as it's not open source):

            var list = obj.FindDataNear(a, b...).Select(i => obj.GetPosition(i))
                .Where(...long lambda...)
                .MoreLINQ()
                .ToList();
          
          So with the style I used, the semicolon is superfluous due to indentation. Are there styles where the semicolon is useful?
          • darby_nine 3 months ago

            > So with the style I used, the semicolon is superfluous due to indentation.

            Eh, indentation is also conflated with block delimitation. The semicolon is still useful to more strongly indicate statement delimitation at a glance.

            Yes, it's redundant, but so are many signifiers around us. The pity is that readability aspects aren't semantically relevant but are stored as if they are.

  • voidUpdate 3 months ago

    The end of the line isn't always the end of the line, such is if there is a chain of methods and you are limited to 80 columns. Then you can just wrap on a . , and tell the language where you actually want the line to end

  • ilyagr 3 months ago
    • trealira 3 months ago

      Haskell also inserts semicolons, but it has a different rule, which I think is a bit interesting.

      If the current line starts on the same line that the previous expression started on, then a semicolon is inserted at the beginning of the current line. There are also some messy rules about opening and closing braces being inserted.

      So, this:

        do expr1
           expr2
           do expr3
              expr4
      
      Ends up being parsed as though it were written like this:

        do { expr1
           ; expr2
           do { expr3
              ; expr4
              }
           }
      
      If the next line is indented, it's just taken as a continuation of the previous line's expression, so nothing needs to happen.

      [0]: https://amelia.how/posts/parsing-layout.html

    • xpl 3 months ago

      Also, JavaScript.

      • kazinator 3 months ago

        Bourne and POSIX shell:

          for x in *.txt; do echo $x; done
        
          for x in *.txt
          do
            echo $x
          done
      • gary_0 3 months ago

        And Kotlin and Swift.

      • xigoi 3 months ago

        Except JavaScript does it wrong.

        • trealira 3 months ago

          What makes Go's semicolon insertion algorithm different from JavaScript's? They seem similar to me. Isn't it just that the Go compiler requires very strict formatting, which saves you from getting bitten by errors due to unexpected semicolons?

          • xigoi 3 months ago

            The following (contrived) JavaScript code does not work:

              let x = 5
              (function() { console.log(x) })()
            
            The equivalent Go code works:

              package main
              import "fmt"
              func main() {
                x := 5
                (func() { fmt.Printf("%d", x) })()
              }
            • trealira 3 months ago

              Thanks, that's a good case.

              Actually, the JavaScript semicolon insertion algorithm [0] seems more complex than I had remembered. I had thought of them as variations on the semicolon insertion in BCPL, but it seems like that's an oversimplification.

              For reference, these are the BCPL rules:

              The canonical symbol SEMICOLON is inserted between pairs of items if they appeared on different lines and if the first was from the set of items which may end a command or definition, namely:

                BREAK RETURN FINISH REPEAT SKET RKET 
                SECTKET NAME STRINGCONST NUMBER TRUE FALSE 
              
              and the second is from the set of items which may start: a command, namely:

                TEST FOR IF UNLESS UNTIL WHILE GOTO RESULTIS 
                CASE DEFAULT BREAK RETURN FINISH SECTBRA 
                RBRA VALOF LV RV NAME
              
              ...

              ( ) [ ] § § are used to denote RBRA RKET SBRA SKET SECTBRA and SECTKET.

              [0]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

pasc1878 3 months ago

For another way of removing indentation needed for structure.

Make python a lisp - indentation is just the number of brackets.

Hy - http://hylang.org

  • xigoi 3 months ago

    Lisp-style parentheses are still better than brackets because at least they don’t waste verticat space.

      (if x
        (if y
          (if z
            foo)))
    
    versus

      if (x) {
        if (y) {
          if (z) {
            foo;
          }
        }
      }
    • kazinator 3 months ago

      Braces can be formatted in a Lisp-inspired style!

      Try it like this:

        if (x) 
        { if (y)
          { if (z)
            { foo; } } }
      
      The rules are a little different. We have two-space indentation, like what is favored in Lisp, but there is a space after the opening brace. For symmetry, we put spaces between the closing ones. It works best if we don't "cuddle" the opening brace but put it on a new line.

      There is a rhyme and reason to it, and consistency.

      I've written some C programs that way, though not recently and can't point to any online examples.

      However, I also wrote, and maintain, the Yacc grammar file in TXR Lisp in this style (just the actions in the grammar portion). For whatever reason, it works well in grammar files.

      https://www.kylheku.com/cgit/txr/tree/parser.y

    • pasc1878 3 months ago

      Brackets are these () - so lisp

      {} are braces

      This is English English

      • kazinator 3 months ago

        In British English, it's all brackets: (round) brackets, square brackets, curly brackets, angle brackets. British English admits the term "braces" for curly brackets.

        • pasc1878 3 months ago

          Yep - but as you say brackets on its own is always ()

  • blharr 3 months ago

    I feel like this is a great idea, but as with other lisps, it looks really unfamiliar and loses the simple readability that python has for me.

    • perrygeo 3 months ago

      > it looks really unfamiliar

      Swahili looks unfamiliar to me. Because I didn't grow up in southern Africa. Don't conflate subjective familiarity with objective simplicity - any "unfamiliar" concept only reflects on you, not your subject.

      • goatlover 3 months ago

        But millions of people are already familiar with existing Python syntax. Changing that would make it unfamiliar to them, and that's when you get people switching to another language that looks more familiar to them. Which is why C-style syntax has been so popular.

        • pasc1878 3 months ago

          No one is suggesting changing it. This whole thread is about an alternative syntax for python.

          I was pointing out that there is yet another alternative.

          I prefer lisp syntax over indentation aware (e.g. python) over block syntax and at the bottom ones that force semi colons on you (the end of line is sufficient) - so the OP syntax for me is a massive downgrade of the language.

          Somewhere in that list I would add APL near the top but can't quite categorise it.

p5a0u9l 3 months ago

Glad that auto formatting tools like black and ruff (at least in Python world) are increasingly becoming the norm. It’s really nice to not think about whitespace or humor these silly arguments.

Ringz 3 months ago

“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.”

Antoine de Saint-Exupéry

Unfortunately, we still live in an era where humans have to adapt to technology rather than the other way around. From my perspective, this is particularly true for programming.

For me, Python is a good (though not ideal) mix of simple syntax and power. The language is characterized by low redundancy, meaning it uses fewer unnecessary characters like semicolons or curly braces to mark the end of a line. If a human can recognize the end of a line without special characters, then the compiler should be able to as well.

As someone with ADHD, I find it particularly difficult not to get distracted by these and other superfluous details. These small distractions add up and can become very burdensome. Interestingly, I found it easier to program in Assembler and Modula than in languages like C++ (MSVC), PHP, or JavaScript – at least as long as the projects were small.

Even a brief look at Rust’s syntax causes me almost physical discomfort, no matter how great, powerful, and useful the language may be.

For this reason, I almost exclusively use the terminal for emails, calendar, and programming, even though complex GUIs can simplify some tasks.

Although Python is not perfect in terms of syntax, it offers a good balance. Perhaps one day, before the perfect programming language exists, we will be able to use AI and ML to explain to the computer what a program should do with simple language (better than ChatGPT right now), just like Captain Picard. In fantasy, a few letters, punctuation marks, and some grammar is all that is needed. This may lead to inaccuracies in human-to-human communication, but that does not mean the same problems must occur in communication with an intelligent compiler.

Making syntax as “human-readable” as possible should always be the highest priority. We could unlock so much potential this way.

  • masklinn 3 months ago

    > For me, Python is a good (though not ideal) mix of simple syntax and power. The language is characterized by low redundancy, meaning it uses fewer unnecessary characters like semicolons or curly braces to mark the end of a line. If a human can recognize the end of a line without special characters, then the compiler should be able to as well. […] Even a brief look at Rust’s syntax

    That’s a shame because you’re missing that these sigils actually have meaning there, because the semantics of the language are completely different: Python is statements-based with very limited scoping (global and function), Rust is expression based with block scoping.

    As a result, blocks (paired braces) are a way to pack multiple statements into an expression e.g.

        let v = {
            let a = thing1();
            let b = thing2();
            thing3(a, b)
        };
    
    And `;` is not an alias for end-of-line, it’s a separator for statements.

    And not aliasing end-of-line to end-of-statement is relevant to rust being expression oriented, it’s very common for expressions to span multiple lines, in that case Python requires either wrapping the entire thing in parenthesis or escaping the EOL with `\`.

    Could you find other ways to do this? Sure, but then you have to make other tradeoffs e.g. wrap everything in matching symbols à la lisp, or make statements into special cases à la Haskell.

    • mavhc 3 months ago

      Wrapping 99% of things in {} seems worse than wrapping 1% of things in ()

    • xigoi 3 months ago

      > the semantics of the language are completely different: Python is statements-based with very limited scoping (global and function), Rust is expression based with block scoping.

      This is a red herring. Haskell, CoffeeScript, Nim, Lean, etc. are expression-oriented and use indentation like Python, while C(++), Java, JavaScript, etc. are statement-oriented and use braces.

    • Ringz 3 months ago

      > And `;` is not an alias for end-of-line, it’s a separator for statements.

      And in Python \n is not an alias for end-of-line, it’s a separator for statements.

    • wqtrez 3 months ago

      That looks very clean, though the deviation from OCaml takes a minute to get used to.

  • __jonas 3 months ago

    > Making syntax as “human-readable” as possible should always be the highest priority. We could unlock so much potential this way.

    I think there is a balance to strike here.

    I often like to work with code by cutting and pasting sections around and then hitting the format hotkey to align everything.

    I enjoy the guarantee that as long as the syntax is correct, it doesn't matter how I type out the code because I'll just hit the formatter hotkey immediately afterwards and it will apply the correct indentation and lay it all out nicely

    Obviously that's impossible in Python and it makes working with it really frustrating to me, it feels so delicate, I almost don't want to touch the code because I'm always accidentally changing the indentation, it's a real limit of this "human-readable" syntax in my opinion.

    • Ringz 3 months ago

      That’s definitely possible in Python. Maybe not if you’re using the simplest text editor. But regardless of whether it’s NVIM or Visual Studio Code, you can easily jump to the end of a line, press Return, and the code will be inserted with the correct indentation. RUFF or BLACK do the rest, and they do it quite intelligently.

      • __jonas 3 months ago

        Oh interesting, I didn't know! How reliable is it? Does it work well even if you partly copy functions / with blocks etc. ?

        I just tried it in vscode, it didn't work at all, copy pasted a single line to another function and it kept its indentation and vscode showed a pylance error about unexpected indentation.

        I just have the official Python extension by Microsoft, perhaps some more configuration is required?

        I don't really write any Python, I'm sure there is a way to improve the experience.

    • xigoi 3 months ago

      > Obviously that's impossible in Python and it makes working with it really frustrating to me, it feels so delicate, I almost don't want to touch the code because I'm always accidentally changing the indentation

      Skill issue. I just press my “paste with correct indentation” hotkey and move on.

  • madeofpalk 3 months ago

    > Unfortunately, we still live in an era where humans have to adapt to technology rather than the other way around. From my perspective, this is particularly true for programming.

    I think it's interesting that you say this, and point it towards Python.

    Personally, with Python's significant whitespace, I feel more constrained writing code in a style that I prefer, with the computer requiring me to adapt to it, compared to other languages. I see code with braces and semi-colons more freeing because I get more control over the line structure.

    At the end of the day, it's all stylistic personal preference. Python isn't the evolutionary ideal form for programming languages, it's just what some people prefer.

  • wqtrez 3 months ago

    The Saint-Exupéry quote applies to Lisp, may in some manner apply to Python 2.7, but certainly not to Python 3.12.

    Many people here argue that braces do provide some structure that helps in understanding and navigating the program. Python files over 100 lines with a lot of if-statements become syntactically unreadable.

    So taking them away does not help.

    Generally, minimalism (except for the Lisp-style one) is not always good. Python is called executable pseudo-code. Do academics use it to specify algorithms?

    No, most still use some form of Pascal/Algol style syntax, which conveys the meaning much better.

    • Ringz 3 months ago

      > The Saint-Exupéry quote applies to Lisp, may in some manner apply to Python 2.7, but certainly not to Python 3.12.

      Is the syntax not about 80% the same? And isn't most of that "same simple syntax" commonly used daily?

      > Many people here argue that braces do provide some structure that helps in understanding and navigating the program. Python files over 100 lines with a lot of if-statements become syntactically unreadable.

      That's probably True. But poor programming discipline and syntax that eases reading problematic code also contribute to this issue.

      > So taking them away does not help. For me it actually promotes better coding style and hygiene.

      > Generally, minimalism (except for the Lisp-style one) is not always good. The quote was about perfectionism, not minimalism.

  • kazinator 3 months ago

    There is already nothing left to take away before you've made anything, so just don't start the project and you have perfection.

usrbinbash 3 months ago

The problem I have with such tools, is interoperability.

This transpiles into Python. Okay. So for this to work in a collaborative environment, EVERYONE working on the code has to use it. Given how popular python is, and the natural inertia of programming languages, I simply don't see that happening.

The reasons for this are legion: From programmers simply being used to how python looks, over IDEs and linters that would have to be remade, all the way to automated tooling.

And even if all that were not a problem: This introduces one more step and one more element into the build chain. Which is something I can't see DevOps doing, for a, at the end of the day, purely cosmetic change.

woolion 3 months ago

For those interested in the "no syntax" approach (the editor being aware of the structure and able to operate natively on it), there are a number of projects [0] that go beyond simple Proof of Concepts. Naturally there are more on Lisp-y languages since there is much less work to go back and forth between syntax and structure. Then is another interesting related discussion [1] from 2015, "Programmer Tooling Beyond Plain Text". Since discusses article seems down, I've added the archive link at [2].

[0] https://github.com/yairchu/awesome-structure-editors/blob/ma...

[1] https://news.ycombinator.com/item?id=9495493

[2] https://web.archive.org/web/20151023070244/http://joelburget...

a3w 3 months ago

First of april is not now. So I will seriously discuss the idea:

IMHO, some level of linting should be required. I would often have to reject lengthy and excellent pull requests (PRs), just because autoformat was not pressed and three instead of four whitespaces are in kotlin code. That annoys everyone. Python does that right, code won't compile with the three version whitespace, which is easily spotted before the PR.

  • jaredsohn 3 months ago

    I think that would ideally be done via a separate linter set up in CI.

    It has bugged me when using python interactively but fortunately ipython will ignore it.

  • giancarlostoro 3 months ago

    In Visual Studio I turn on the feature to see whitespaces and non visible characters, just because every now and then, for some ungodly reason, someone in the project, somewhere, in every C# project I've ever worked on, will somehow open the file differently (seriously wtf? we all use Visual Studio!) and goof up a file somewhere, or there's people who instead of hitting tab, will manually insert spaces in a way that doesn't match Visual Studio's own format.

    • AstroJetson 3 months ago

      I’ll use Visual Studio when you pry my cold dead fingers off of my Vim keyboard. Since Ogg used square rock and Eagg used triangle rock to carve messages we’ve fought over editors. I fall into the camp a of formatter should do the presentation. But I also fall into the { } would be nice for Python.

    • jobigoud 3 months ago

      Most likely copy-pasting code from somewhere else that doesn't use the same convention.

lofaszvanitt 3 months ago

People have these culture wars about braces in the end or new line, while the whole thing should be on the editor's side. It shows you the way you want it, then convert it to the agreed upon style upon saving.

Text editors are easy, but are waaaaay in the past. There could be much much better 3D like editors out there, but everyone is lazy to make one that would make your life much easier.

  • unstable 3 months ago

    > while the whole thing should be on the editor's side.

    This.

    I'd prefer using my own preferences instead of using a dumb formatter like prettier. Who cares some other dev in your team prefers 2 chars indentation? It should be an editor preference, not applied to source code.

    Personally I would also prefer the IDE to do type checking as well so we can get rid of the TypeScript misery, but that's another discussion.

psychoslave 3 months ago

On that side, as for many others, Ruby captures my love. You can use `{…}` or `do … end` as you see best fit. And enforcing some indentation convention is always an option with some upper level tools. What makes perfect sense for integration in a large codebase is ridiculous while interacting with a REPL.

Now Ruby as his own defects of course. Static type can be integrated through Sorbet, but that still something out of the core for now. On that side, PHP had during the last years shown a far more remarkable pace in integrating many advanced feature for OOP (and functional stuffs are also progressing well). That said, the foundation of Ruby still win my preference in term of elegance and feeling of coherence.

I didn’t touch that much Python over the last few years. The only (significant) reason I would see it as opportune is its heavy use in ML and the like domains, and I didn’t have an opportunity to dig this domain much.

  • Sohcahtoa82 3 months ago

    > You can use `{…}` or `do … end` as you see best fit.

    I don't use Ruby, so I don't know what happens in the Ruby world, but...

    Doesn't this create a Holy War akin to C/C++'s fighting over where the opening brace goes (Current line vs next line)?

    • steveklabnik 3 months ago

      It doesn't, because

        3.times do
          print 'Welcome '
        end
      
      this works, but

        3.times
        do
          print 'Welcome '
        end
      
      does not work. Same with curly braces.
      • Sohcahtoa82 3 months ago

        I don't mean where to put the opening "do", I mean, a fight between:

            3.times {
                print 'Welcome '
            }
        
        and

            3.times do
                print 'Welcome '
            end
        • steveklabnik 3 months ago

          Ah!

          So, Ruby is a bit weird: the Ruby community itself tends to be much closer to Perl than Python, that is, the language doesn't mind embracing many ways of doing the same thing. However, the Rails community tends to curb this attitude a bit by being really strongly about conventions, and following them.

          In practice, this means that a significant amount of the community uses one of the two rules:

          > Use {} for one line blocks, use do/end for multiline blocks.

          or

          > Use {} for blocks that produce a value, use do/end for side effects.

          The latter is called "Weirich style," after a very prominent Rubyist using that style.

          Hilariously, your example would be code that could go either way, depending on which style you choose. Though I would think that people who subscribe to the first rule would write it

             3.times { print 'Welcome ' }
          
          as the "one line" really kinda leans this way.

          Anyway that's as far as I know, my Ruby knowledge is about 10 years old at this point, so maybe things have evolved since then, but I haven't really heard of any changes here.

Fraterkes 3 months ago

Is significant whitespace good or bad? Maybe 3/7/2024 is finally the day we get to the bottom of this.

  • efilife 3 months ago

    Bad. Further discussion below

    • kazinator 3 months ago

      Below here. It has been determined that discussion is not required.

      • enricotr 3 months ago

        Ahahahahahahaah

        • 8xeh 3 months ago

          Without significant whitespace, you'd need at least 5 more comments consisting solely of "}" for this reply chain to be syntactically correct.

aitchnyu 3 months ago

Might as well allow multiline lambdas and js-style ternary statements. JS (under JSX skin) makes constructing a tree of components really ergonomic. Similar libraries in Python rely on doing side effects and context managers and dsls.

Also TS has slightly more consistent syntax for return types than Python. ``` // TS

function fn(a: Type, b: Type) : Type {

}

// Python def fn(a: Type, b:Type) -> Type {

} ```

But I want python to have to close braces on as few lines as possible. Yes I'm a Black user and wonder how.

IshKebab 3 months ago

Of all the things to hate about Python, this seems like the least. The indentation definitely looks nicer. I'd say the only real disadvantages it has are a) you are definitely restricted to statement-based constructs; no inline function definitions etc., and b) pasting stuff into the REPL is a mess.

They could fix the latter, but the REPL is Python tooling so it is required to be awful.

  • xigoi 3 months ago

    The statement thing could also be fixed. CoffeeScript, for example, is indentation-based and supports multiline expressions.

    • IshKebab 3 months ago

      I had a skim of it but honestly it looks like it just gets really confusing. Like you have to spend time just mentally parsing the code. Not really what I want.

      Similar to OCaml which is very light on punctuation - code just ends up like a sequence of words, with an occasional comma and it's quite mentally taxing to figure out where the functions and parameters are.

glimmung 3 months ago

I'm glad this exists for those who want it, but for me the added noise / cognitive load of all those braces is painful.

calmbonsai 3 months ago

With Python, use Black or go home.

  • vaylian 3 months ago

    This. There are situations where I don't agree with the Black formatting, but none of them bother me enough to drop Black. Automatic consistent code formatting is very nice, especially when you need to work with other people on the same code.

  • emmelaich 3 months ago

    Never heard of it so looked it up:

    https://github.com/psf/black

    > Black is the uncompromising Python code formatter. By using it, you agree to cede control over minutiae of hand-formatting. In return, Black gives you speed, determinism, and freedom from pycodestyle nagging about formatting. You will save time and mental energy for more important matters.

  • Sohcahtoa82 3 months ago

    Yup. We use Black where I work. It runs on every PR and we don't approve PRs that aren't approved by Black. Most of us have created a pre-commit hook so we don't even make commits that Black won't like.

teddyh 3 months ago

The documentation notes that reserving braces for blocks makes it very ugly to deal with dict literals, but it’t also terrible for sets, set comprehensions, and dict comprehensions. You’d think they’d choose some other characters than braces in order to avoid this. I seem to recall that RPL used « and » for program blocks.

  • signaru 3 months ago

    begin/end might be more familiar. Some languages don't even have the equivalent of (Pascal's) "begin" since other keywords are already associated with starting a block.

    • mrspuratic 3 months ago

      A long time ago this type of thing ("make C look like pascal") used to be the subject of holy wars/trolling

        #define BEGIN {
        #define END  } 
      
      There is, to this day afaict, a warning suppression option in VisualStudio for pre-processor macros with unbalanced braces that uses exactly this as an example.
  • mwkaufma 3 months ago

    Why are braces-for-both-blocks-and-literals/etc a deal breaker here, but not in JS?

    • jerf 3 months ago

      Because bython is basically a glorified regular expression search and replace: https://github.com/mathialo/bython/blob/master/bython/parser...

      Rather than a real parser. A real parser knows about the context it is in, and as long as the grammar is unambiguous about some character, it can be reused in as many distinct parser constructions as you like. A pure regex-based approach to a first approximation can not.

      Whether or not it absolutely can or can't, without "approximation" and with regard to the exact re library in Python, would be something you'd have to work out through tedious effort. Regexes with backtracking can do a lot more than mathematical regexes, as well as all the other elaborations you could use. But even if Python's re can do it, you will be better off with a real parser.

      The "correct" solution, since by design Python and Bython share the same AST, is to take some existing code that can parse and re-emit Python code without changing it, tweak the incoming grammar to use braces instead, then emit the AST back out as Python. Then you wouldn't have this problem, or the problem with comments referenced in the source code (line 109 of the file I linked, just up a bit), or any of the probably other many little issues that would arise on real code if you tried to put this in real use. The only slight complication I can see is there may be a slight issue with comments around the braces. I'm not sure, and I'm not going to sit here & work it out fully for an HN post.

      Also, this is not a criticism of Bython. The author can do as they please with it. If nothing else you can always label this a prototype. Prototyping is good, right? Anyone who was rushing to slam this into production is just gonna learn a real valuable lesson worth its weight in gold, and not Bython's fault.

    • throwitaway1123 3 months ago

      Using braces in an arrow function that returns an object literal actually is ambiguous in JS, which is why you have to wrap it in parentheses, e.g.:

        const foo = () => ({foo: 'bar'})
      
      If you omit the parentheses it gets interpreted as a block with a label and a string literal:

        const baz = () => {baz: 'bar'}
      
      https://astexplorer.net/#/gist/9a86e0b61fda312dce2ea9d10d37f...
    • wfleming 3 months ago

      Probably because that makes parsing much more complicated, and this being a half-joking hobbyist project they didn’t want to increase scope that much.

adolph 3 months ago

I had to do a quick check if python do have teeth and thus use braces. My initial thought was that they do not as the most prominent teeth on snakes are fangs and python are not venomous. They do have teeth for holding their pray as they constrict it.

Pythons use their sharp, backward-curving teeth, four rows in the upper jaw, two in the lower, to grasp prey which is then killed by constriction; after an animal has been grasped to restrain it, the python quickly wraps a number of coils around it. Death occurs primarily by cardiac arrest.

https://en.wikipedia.org/wiki/Pythonidae

0x1ceb00da 3 months ago

Could've been a python parser patch because it adds a preprocessing step. Wouldn't have been that difficult to maintain since the syntax doesn't change that much.

  • make3 3 months ago

    but then you can't pip install it, & you have to re build your whole environments, etc

pansa2 3 months ago

Does this add support for multiple-statement lambdas?

IMO lack of support for them (because of the lack of a good syntax) is the main downside of Python’s significant indentation.

  • Sohcahtoa82 3 months ago

    I've never understood the strong demand for multi-statement lambdas. At best, it's just syntactic sugar. What's wrong with:

    def my_map_function(x): # do stuff

    new_list = map(my_map_function, my_list)

    ?

bloopernova 3 months ago

I've recently created a couple of Lambdas using nodejs rather than my normal Python.

Despite node feeling more verbose, I've found that I understand node easier than Python. It's definitely strange to me, because there can't be that much difference between the 2, but parentheses seem to make it easier to follow structure?

  • 65 3 months ago

    I've written a lot of Python and Javascript and still prefer Javascript (Typescript) over Python. I like how easy it is to do functional programming with Javascript. Python can have some weird syntax for functional programming, whereas Javascript has very obvious ways to do something such as an array map. To me Python feels more like PHP than Javascript.

    • demondemidi 3 months ago

      Python async syntax is ass backwards compared to JS.

thih9 3 months ago

> You should still write beautiful code, but if you mess up with tabs/spaces, or copy one piece of code to another that uses a different indentation style, it won't break.

This seems contradictory. But I see the benefits. Perhaps braces and an official linter would be a more ergonomic approach.

lionkor 3 months ago

All significant characters should be non-empty/visible, I think that sums up why I prefer braces.

  • makeitdouble 3 months ago

    It's weird to me to as a programmer to categorize space/tabs and new lines as empty or invisible.

    It only makes sense if you're writing by hand on paper or designing a page, sure wherever you don't write is empty. But even then that's still visible space.

    Then most language we currently use still rely on spaces in critical ways. `public function a()` and `publicfunctiona()`are not equivalent and there's no replacement character for the spaces.

    Now, more power to you to like braces, same way some languages like dollar signs.

  • cardanome 3 months ago

    Nearly every editor has a "show whitespace" option.[0]

    I still don't understand why some people don't use it. Even in non-whitespace sensitive languages, I need to see the whitespace so that I can tell if the formatting is off or not. Also make the code easier to read as I can literally see how far the code is intended instead of having to guess by amount of space.

    Sure, automatic code formatting solves most of the issues but it is still good to have actual control over your whitespace.

    [0] Except VIM which vexes me greatly. Might be one of the reasons whitespace sensitive languages are disliked by certain programmers?

    • chrismorgan 3 months ago

      > Nearly every editor has a "show whitespace" option. Except VIM

      Sure it does. See 'list' and 'listchars'.

      • cardanome 3 months ago

        Which looks ugly as hell per default and I have never gotten to work quite right for me

        • PhilipRoman 3 months ago

          I use something like this for my daily work vimrc:

              set list listchars=tab:›\ ,multispace:·
          
          The only thing I hate about vim's treatment of indents is having separate settings for shiftwidth and tabsize.
  • Culonavirus 3 months ago

    Only monsters prefer invisible characters having syntactic meaning, and most of them probably also like pineapple on pizza. Shameful. (j/k)

    • dajtxx 3 months ago

      I agree entirely with the above, not kidding.

  • xigoi 3 months ago

    If you can’t see whether a line is indented, you need to visit an eye doctor urgently.

JodieBenitez 3 months ago

I had to check the calendar. Twice.

wiml 3 months ago

Didn't Python used to support braces as an alternative to indentation? I remember it being a feature back in the 1.x days, but I can't find it in the old language docs, so I must be thinking of some other language.

ivanche 3 months ago

As they say, python looks exactly like Guido indented it to look.

dmurray 3 months ago

> At the moment, Bython is written in Python.

PR #1: Makes Bython self-hosting

hoosieree 3 months ago

mascot: a python, with braces

sambalbadjak 3 months ago

I did not know I had such a strong reaction to seeing curly braces in python. brr not my cup of tea. but all the power to you

sgt101 3 months ago

I don't like whitespace compulsion but I can live with it.

self.onandonandon is a real pain along with copy.deepcopy

samatman 3 months ago

I was wondering if this was sincere or a troll, until I saw the semicolons.

Troll. 100%. A good one at that.

pyuser583 3 months ago

Python supports extensions. Maybe a better way than translating text files?

RyEgswuCsn 3 months ago

People spent considerable amount of effort developing systems that separate contents from styles (latex, html/css, etc). And with Python people think it’s a good idea to encode contents as styles…

autoexec 3 months ago

Honestly, the weird whitespace annoyance doesn't bother me half as much as needing parentheses for print.

  • Sohcahtoa82 3 months ago

    The parentheses make sense because print is a function that has parameters, and more than just the string to be printed.

    https://docs.python.org/3/library/functions.html#print

    I suppose they could have given the option to continue using print as a statement if you don't care to override the default parameters, but having those parameters really simplified some options.

shantnutiwari 3 months ago

The library is 6 years old, and I remember we all laughed when it came out. Why is it on the 1st page now?

math_dandy 3 months ago

Should write a PEG grammar.

mort96 3 months ago

Honestly, this looks more readable than Python. Noticing whether something is 3 or 4 levels less indented than something else is really really hard. Noticing whether there are 3 or 4 braces is easy.

  • jjallen 3 months ago

    Why not use your editor to do this? I would never expend mental energy doing something this trivial in 2024.

    • mort96 3 months ago

      Use my editor to do .. what exactly?

      • rented_mule 3 months ago

        Use what are often called "indentation guides". Here's an extreme form of them from the blockman extension for vscode: https://raw.githubusercontent.com/leodevbro/vscode-blockman/...

        • mort96 3 months ago

          1) that looks incredibly cluttered (yes, even compared to braces), and 2) it doesn't help a whole lot when reading code in any context what so ever which is outside of my preferred editor (including in github/gitlab merge requests or 'git diff' locally)

          • rented_mule 3 months ago

            For me, what is visual clutter is all about what I'm used to. After a short period of adaptation, I found indentation guides disappeared when I was looking for them. You can also choose your styling. As I mentioned above, that was an extreme example. Here's a style that adds very little clutter (mine look a lot like this): https://i.sstatic.net/nxPrP.png

            Also in the spirit of modern tooling, VSCode has had the ability to navigate GitHub Pull Requests, with all the normal code editing tooling, since 2018. I'd be surprised if it's alone in that ability in 2024. The same is possible with Gitlab Merge Requests using Gitlab's own extension. I can also use VSCode to remotely edit on almost any Linux/Mac/Windows machine that I can ssh into, or inside Docker containers.

          • xigoi 3 months ago

            Unlike braces, indent guides don’t take up vertical space, so it’s much less cluttered.

      • mixmastamyk 3 months ago

        Indentation guides have been a thing in editors for about thirty? years. Geany supports them for example. Turn them on and never mistake a level again.

        I also turn on visible whitespace but make the color very subtle in the syntax highlighting section. Makes inconsistencies jump off the screen. Other little features like deleting trailing whitespace are your friend.

        • mort96 3 months ago

          Oh I'll just call Microsoft and ask them to install an indentation guides plug-in to the GitHub merge request diff view, one sec

          • mixmastamyk 3 months ago

            [flagged]

            • mort96 3 months ago

              How do I enable that feature in the GitHub merge request diff view?

              • necovek 3 months ago

                Ignoring the tone of the other poster, the point they are making is that there is no clear value for indentation markers in a (unified) diff view, which is based around lines being removed and added.

                Similarly, you might not even see braces for the corresponding block, so the braces-vs-spaces is not really a win for "braces".

                However, I am guessing you are mostly using side-by-side diff view (as opposed to unified diff view), which might have some value to indicate indentation change for a bigger chunk of the code. But again, if you are not seeing where the block starts or ends with braces in the diff block, why is whitespace in any way "worse"?

              • mixmastamyk 3 months ago

                I just explained why that question is nonsensical. What do you hope to achieve by repeating it?

                • mort96 3 months ago

                  You said:

                  > Everything outside of notepad already supports it—that was the point, dumbass.

                  As a response to me pointing out that it's not supported in the GitHub diff view. That response is nonsensical unless you meant to say that it's supported in the GitHub diff view.

                  • mixmastamyk 3 months ago

                    No one is using block markers or indentation guides in a diff view because that doesn’t make sense. The two+ views would conflict with each other, so vast majority of such tools don’t even try to understand blocks. (difftastic however, on the terminal tries.)

                    If a diff is particularly complex (it shouldn’t but assuming) you’ll need to look at the destination in full and confirm tests etc have passed.

                    Any non-theoretical issues you’d like to discuss?

                    • mort96 3 months ago

                      Let me try again.

                      You said:

                      > Everything outside of notepad already supports it—that was the point, dumbass.

                      As a response to me pointing out that it's not supported in the GitHub diff view. That response is nonsensical unless you meant to say that it's supported in the GitHub diff view

                      • mixmastamyk 3 months ago

                        It's clear that my original statement referred to editors of source code. You then moved the goal posts to "merge diff" views on a website.

                        Despite that, I explained this didn't make sense, diffs being line-based and not block-based and all that.

                        That's two fundamental problems with your line of argument. This is my last reply.

                        • mort96 3 months ago

                          Let me try again.

                          You said:

                          > Everything outside of notepad already supports it—that was the point, dumbass.

                          As a response to me pointing out that it's not supported in the GitHub diff view. That response is nonsensical unless you meant to say that it's supported in the GitHub diff view

      • jjallen 3 months ago

        To reformat your code for you. Quick two strokes should do it. I use Jetbrains and it’s select all -> alt ctrl L I think. Massive timesaver. Anything a computer can do to help coders good IDEs can do in the blink of an eye.

  • necovek 3 months ago

    How much Python have you ever written or reviewed? With only a bit of experience, I am sure you'd have no trouble doing that if the Python code is not using 2-space indentation.

    It certainly becomes a problem if you are looking at a 100+ line method/function, but with Python being as expressive as it is, a 100+ line method/function is a problem unto itself.

    Otherwise, I've never had any issues with it — even with languages other than Python, I mostly rely on white space and alignment to understand the block boundaries, only resorting to reviewing the braces carefully when something is amiss.

  • Myrmornis 3 months ago

    I hope you don't have to do that very often. Occasionally, sure, but a lot of functions that have an indentation drop of 3 or 4 levels would be better refactored.

    • mort96 3 months ago

      I'll remember to tell that to everybody whose code I could ever have to read in the future but I don't think it'll have much effect, we're talking at thousands of people I'm guessing and I don't know most of them

cynicalsecurity 3 months ago

The same goes for Golang. The reverse position of a variable name and type in function arguments is absolutely infuriating. I hate the person who did it, it's absolutely stupid.

newaccountman2 3 months ago

I think Python is terrible, but whitespace is ok. lol

teddyh 3 months ago

  >>> from __future__ import braces
  File "<stdin>", line 1
  SyntaxError: not a chance
  >>>
  • kibwen 3 months ago

    Joke's on Python, it already supports braces:

       def foo(): #{
           if True: #{
               print("The future is now, old man")
           #}
       #}
    • gedy 3 months ago

      Ha cool, you could probably make a font with ligatures to hide the # too

      • kazinator 3 months ago

        More than that, you could write a tool which checks the consistency of your indentation against your #{ and #}.

        This has advantages over using a generation tool that has to strip away braces to produce valid Python.

    • giancarlostoro 3 months ago

      I was going to complain that they need to be on separate lines, and then I realized it would work that way, though PEP-8 and Pycharm might complain.

Aeium 3 months ago

[flagged]

scld 3 months ago

[flagged]

  • apantel 3 months ago

    { ew; }

    • a3w 3 months ago

      Exactly: Like `ew`, but worse.

AcerbicZero 3 months ago

Whitespace is def wrong, but I'm not sure this actually makes things much better....still pretty awesome idea!

kaplpot 3 months ago

This is the least of Python's problems, but makes for a good populist discussion that will keep Python on the front page for yet another 10 hours.

This is how Python got big: Discuss cute issues endlessly, pretend to be a funny, benevolent community. But real issues like performance, correctness or security are never addressed, and people who dare to mention them are punished severely.

  • GaryNumanVevo 3 months ago

    This is a very shallow understanding of the Python community. Of course there are a lot of "cute issue discussions" it's a language with a huge number of diverse participants. Performance and security are regularly discussed and patches are contributed via the mailing list. Python is _the_ language for ML right now because of the community.

    • cmalexn 3 months ago

      Again, the ideal version that is removed from reality is presented.

      The mailing lists are non-operational for political reasons and because most competent people have left. Patches have never been contributed via the mailing lists.

      Python is the language for ML not because of the "community", which is an exploitative system where talkers who go on stage at a PyCon and never do anything get more money and worse, control who can earn money in the Python ecosystem.

      It is the language for ML because Python had a decent C-API and a lot of scientific software has been written early on.

      • HexDecOctBin 3 months ago

        This is something I have been thinking about. Why was a lot of scientific software written in Python?

        Remember that Torch originally had a Lua frontend, and was only later turned into PyTorch, citing the same availability of scientific software.

        But considering that Lua has a far better C API than Python, why did those initial scientific/mathematical software use Python?

        • masklinn 3 months ago

          Because the core Python team started working with scientific communities very early on, matrix-sig was created in 1995 and led to a bunch of conveniences from e.g. rich indexing (slices and implicit tuples in brackets) to matmul. `table.unpack` and having to convert rich keys to format rich keys into strings is not an upgrade.

          And Lua has a great API for calling into C, but for exposing lua APIs from C you’re basically writing bytecode for a stack VM in C. This is not very fun to expose large rich APIs.

          An other significant divergence is because Lua primarily targets embedding rather than freestanding, backwards compatibility is pretty far down the list of considerations, you’re not going to do a major lua upgrade once you’ve released your game.

          Python had one major compatibility break 5~15 years ago (depending when you switched) and teeth are still gnashing over it, Lua does that much every major version.

        • dist-epoch 3 months ago

          Lua may have a better C API, but it's a small and not very useful language.

          Python C API is one of the better ones, it's extremely easy to connect C/C++ code to Python.

          Python is also extremely good at reshaping data, parsing files, scraping data and so on - the preprocessing part required by many scientific computations.

  • rtpg 3 months ago

    Correctness? I feel like in the world of Javascript and Ruby (and hell, even Julia with some of its really gnarly bugs!), Python is pretty serious about having code do what it's supposed to do. There are surprises downstream, but a hell of a lot than other languages IMO