[HN Gopher] Python with Braces
       ___________________________________________________________________
        
       Python with Braces
        
       Author : punnerud
       Score  : 65 points
       Date   : 2024-07-03 14:05 UTC (4 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | teddyh wrote:
       | >>> from __future__ import braces       File "<stdin>", line 1
       | SyntaxError: not a chance       >>>
        
         | kibwen wrote:
         | Joke's on Python, it already supports braces:
         | def foo(): #{            if True: #{                print("The
         | future is now, old man")            #}        #}
        
           | gedy wrote:
           | Ha cool, you could probably make a font with ligatures to
           | hide the # too
        
             | kazinator wrote:
             | 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 wrote:
           | 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.
        
       | mort96 wrote:
       | 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 wrote:
         | Why not use your editor to do this? I would never expend mental
         | energy doing something this trivial in 2024.
        
           | teddyh wrote:
           | Yes. A quick search yielded:
           | <https://github.com/DarthFennec/highlight-indent-guides>
        
           | mort96 wrote:
           | Use my editor to do .. what exactly?
        
             | rented_mule wrote:
             | 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 wrote:
               | 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 wrote:
               | 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 wrote:
               | Unlike braces, indent guides don't take up vertical
               | space, so it's much less cluttered.
        
             | mixmastamyk wrote:
             | 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 wrote:
               | 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 wrote:
               | Everything outside of notepad already supports it--that
               | was the point, dumbass.
               | 
               | Diffs are not an area where it (or braces) are useful
               | anyway, due to the merge of the two views.
        
               | mort96 wrote:
               | How do I enable that feature in the GitHub merge request
               | diff view?
        
               | mixmastamyk wrote:
               | I just explained why that question is nonsensical. What
               | do you hope to achieve by repeating it?
        
               | mort96 wrote:
               | 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 wrote:
               | 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 wrote:
               | 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 wrote:
               | 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 wrote:
               | 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
        
               | necovek wrote:
               | 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"?
        
             | jjallen wrote:
             | 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.
        
         | Myrmornis wrote:
         | 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 wrote:
           | 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
        
         | necovek wrote:
         | 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.
        
       | adolph wrote:
       | 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
        
         | m463 wrote:
         | Do they have colons, or semi-colons?
         | 
         | They seem to have semi-lungs, with a right lung and a vestigial
         | left lung
         | 
         | https://upload.wikimedia.org/wikipedia/commons/4/4d/Snake-an...
        
       | Fraterkes wrote:
       | Is significant whitespace good or bad? Maybe 3/7/2024 is finally
       | the day we get to the bottom of this.
        
         | efilife wrote:
         | Bad. Further discussion below
        
           | kazinator wrote:
           | Below here. It has been determined that discussion is not
           | required.
        
             | enricotr wrote:
             | Ahahahahahahaah
        
               | 8xeh wrote:
               | Without significant whitespace, you'd need at least 5
               | more comments consisting solely of "}" for this reply
               | chain to be syntactically correct.
        
       | gary_0 wrote:
       | 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).
        
         | ilyagr wrote:
         | This is what golang does.
         | 
         | https://go.dev/doc/effective_go#semicolons
        
           | xpl wrote:
           | Also, JavaScript.
        
             | gary_0 wrote:
             | And Kotlin and Swift.
        
             | xigoi wrote:
             | Except JavaScript does it wrong.
        
               | trealira wrote:
               | 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 wrote:
               | 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 wrote:
               | 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
               | 
               | ...
               | 
               |  _( ) [ ] SS SS are used to denote RBRA RKET SBRA SKET
               | SECTBRA and SECTKET._
               | 
               | [0]: https://developer.mozilla.org/en-
               | US/docs/Web/JavaScript/Refe...
        
             | kazinator wrote:
             | Bourne and POSIX shell:                 for x in *.txt; do
             | echo $x; done            for x in *.txt       do
             | echo $x       done
        
           | trealira wrote:
           | 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
        
         | nomel wrote:
         | 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 wrote:
         | > 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 wrote:
           | > code with very horizontal coding styles
           | 
           | I'm not sure what you mean. Could you give an example?
        
             | darby_nine wrote:
             | Literally just code with long lines. You run into this
             | particularly with monadic stuff like LINQ queries.
        
       | a3w wrote:
       | 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.
        
         | giancarlostoro wrote:
         | 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.
        
       | teddyh wrote:
       | 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.
        
         | mwkaufma wrote:
         | Why are braces-for-both-blocks-and-literals/etc a deal breaker
         | here, but not in JS?
        
           | throwitaway1123 wrote:
           | 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 wrote:
           | 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.
        
           | jerf wrote:
           | Because bython is basically a glorified regular expression
           | search and replace: https://github.com/mathialo/bython/blob/m
           | aster/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.
        
       | sgt101 wrote:
       | I don't like whitespace compulsion but I can live with it.
       | 
       | self.onandonandon is a real pain along with copy.deepcopy
        
       | AcerbicZero wrote:
       | Whitespace is def wrong, but I'm not sure this actually makes
       | things much better....still pretty awesome idea!
        
       | hoosieree wrote:
       | mascot: a python, with braces
        
       | IshKebab wrote:
       | 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 wrote:
         | The statement thing could also be fixed. CoffeeScript, for
         | example, is indentation-based and supports multiline
         | expressions.
        
           | IshKebab wrote:
           | 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.
        
       | 12_throw_away wrote:
       | 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.
        
         | rthnbgrredf wrote:
         | 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.
        
           | randomtoast wrote:
           | 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 wrote:
             | 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.
        
         | TOGoS wrote:
         | 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.
        
       | gabrielsroka wrote:
       | I found this here years ago: Python With Kurly braces.
       | 
       | https://github.com/umlet/pwk
        
       | glimmung wrote:
       | I'm glad this exists for those who want it, but for me the added
       | noise / cognitive load of all those braces is painful.
        
       | pasc1878 wrote:
       | For another way of removing indentation needed for structure.
       | 
       | Make python a lisp - indentation is just the number of brackets.
       | 
       | Hy - http://hylang.org
        
       | darby_nine wrote:
       | 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 wrote:
         | 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...
        
         | islandert wrote:
         | 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.
        
           | kriiuuu wrote:
           | Unison would fit here
        
       | necovek wrote:
       | 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.
        
         | mjevans wrote:
         | 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.
        
       | lionkor wrote:
       | All significant characters should be non-empty/visible, I think
       | that sums up why I prefer braces.
        
         | Culonavirus wrote:
         | Only monsters prefer invisible characters having syntactic
         | meaning, and most of them probably also like pineapple on
         | pizza. Shameful. (j/k)
        
         | makeitdouble wrote:
         | 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.
        
       | dmurray wrote:
       | > At the moment, Bython is written in Python.
       | 
       | PR #1: Makes Bython self-hosting
        
       | calmbonsai wrote:
       | With Python, use Black or go home.
        
       ___________________________________________________________________
       (page generated 2024-07-07 23:00 UTC)