Adding syntax to the CPython interpreter

(leontrolski.github.io)

70 points | by leontrolski 2 days ago ago

24 comments

  • cpburns2009 23 minutes ago

    For all of the syntax features Python has been adding over the years, this would be a nice enhancement: making the "else None" optional in the ternary if-expression. E.g.,

        spam = eggs if bar
        # vs
        spam = eggs if bar else None
  • nickpresta 3 hours ago

    The linked, more detailed post in the article is far more interesting: https://miguendes.me/what-if-python-had-this-ruby-feature

  • nemoniac 2 hours ago

    You could argue that this is not merely adding syntax, but also adding the associated semantics.

    Anyway, if you found this interesting, you might enjoy Eli Bendersky's blog post from nearly 15 years ago where he adds an "until ... do" statement to Python.

    https://eli.thegreenplace.net/2010/06/30/python-internals-ad...

    • pansa2 2 hours ago

      That blog post seems a lot more involved - it adds code to the bytecode compiler as well as to the parser.

      I suspect that’s mostly because the `until` statement is more complex - but another factor seems to be Python’s change in parsing technology from LL(1) to PEG.

    • asplake 2 hours ago

      I sometimes think it would be fun to do “do: ... where:/while/until”, wherein the “where” part does local bindings.

  • dig1 an hour ago

    This is where Lisp-like languages excel with macros. An example in Clojure:

        (defmacro do* [body expr cond]
         `(~expr ~cond
           ~body))
    
         (do* (println "hello") if true)
         (do* (println "hello") when-not (> 1 2))
  • bbb651 9 minutes ago

    You can almost do it with `condition and value`, but you get `False` instead of `None` (and adding any more code makes this worse than `value if condition else None`. Interestingly lua like `<condition> and <true-expression> or <false-expression>` ternaries actually work in python, with the added footgun that <true-expression> must be truthy and people will despise you).

    Rust for example has a solution for this in std, there's a `bool::and_some` method (and `bool::then` that takes a closure to avoid eagerly evaluating the value), but `if { ... }` isn't an expression like `if { ... } else { ... }` is, probably to avoid coupling the language to `Option`.

  • zitterbewegung an hour ago

    This is a cool article. If you want to understand how to contribute to python there is a guide at https://devguide.python.org

    • tmgehrmann 33 minutes ago

      Be aware, however, that the inner circle will use you, take your contributions, and, if you develop own opinions, publicly ban and defame you without any possibility of setting any record straight.

      pyhton-dev is a corporate shark tank where only personalities and employer matter (good code or ideas are optional).

      • pas 3 minutes ago

        That's a pretty strong claim, (and since most inner circles are hard to get into, I even assume it's not without any basis in reality), yet could you please provide some exhibits to support it?

  • pkolchanov 2 hours ago

    Great post!

    I have worked on a similar series of CPython customization articles that you might find interesting:

    https://github.com/pkolchanov/CustomizingPython

  • tgv an hour ago

    Great, now you have the dangling else in python, the one thing that actually was solved by significant white space.

  • Y_Y 2 hours ago

    If only there was a language that let you modify the interpreter on the fly so you could do this as part of normal execution...

    • BiteCode_dev 2 hours ago

      Python can actually do this using "# coding:", albeit less elegantly than lisp.

      I would say it's a good thing, I don't want to see a hundred of half baked, badly tested and vaguely document DSL with no decent tooling support.

      • develatio an hour ago

        Can you provide some more info / links regarding the “# coding:” feature? I wasn’t able to find anything.

        • BiteCode_dev 14 minutes ago

          Codecs (https://docs.python.org/3/library/codecs.html) can change the content of the file on the fly. You can abuse that to create new syntax, although it is evidently not the original intent.

          Let's say you hate significative spaces, here is a (very fragile) PoC for your pain:

          https://0bin.net/paste/42AQCTIC#dLEscW0rWQbE70cdnVCCiY72VuJw...

          Import that into a *.pth file in your venv, and you can then do:

              # coding: braces_indent
           
              def main() {
                  print("Hello, World!")
                  if True {
                      print("This is indented using braces.")
                  }
              }
          
          You also can use import hooks (python ideas does that), bytecode manipulations (pytest does that) or use the ctypes module (forbiddenfruit does that).

          Still, I'm very happy it stays limited to super specific niches. Big power, big responsibilities, and all that.

        • JackC 27 minutes ago

          The idea is you can register a custom file encoding, analogous to built-in file encodings like utf-8, and use it to transform the source file before python loads it. An example is pyxl, kind of like jsx, where you put `# coding: pyxl` at the top and then it will transform bare `<html>` in the python file into calls to a template builder: https://github.com/gvanrossum/pyxl3

          Incidentally this turns out to be super hard to search for without asking an LLM, since "python coding" is so overloaded, and using the feature this way is intentionally undocumented because it's not really what it's for, and not something I think most python users really want to encourage. So, forbidden python knowledge!

        • klibertp 29 minutes ago

          If you place `# coding: utf-8` on the first line of a Python script, it'll try to interpret the raw bytes contained later in the file by passing them through a relevant codec[1]. Since the codec receives the raw source and transforms it before any interpretation happens, you can (here's the point I'm starting to guess) supply a codec that parses the code, transforms the AST, and dumps it back to the source for execution. It would be similar to how "parse transforms" work in Erlang, though there you're handed AST and not bytes.

          [1] https://docs.python.org/3/library/codecs.html

    • klibertp an hour ago

      You're Lisp-baiting, aren't you? ;) I'd add Elixir next to Nim (already mentioned); also Rust. Recently, also Scala.

      The reason we don't have such metaprogramming available everywhere is mostly because you have to subscribe to a particular ideology to allow it. If you think programmers are generally intelligent and responsible, you put macros and metaclasses in your language. If, on the other hand, you think most programmers are dumb code monkeys (with a few exceptions, maybe) your language becomes like early Java or early Go.

      • Y_Y an hour ago

        (Isn't lisp-baiting the raison d'être of hn?)

        Since you mention it, Python does have a fairly elaborate metaclass system, but it seems like it's only really used for implementing the language and rarely if ever wielded by "users". I guess that's a reflection of the language ideology you're talking about.

        Also for what it's worth, I know myself to be a dumb code monkey, but being in the CRUD gutter doesn't preclude me from looking at the metasyntactic stars.

      • keybored an hour ago

        That dichotomy is interesting considering Guy Steele’s Growing a Language talk and his Scheme background. But maybe just mentioning Scheme is misleading here...

    • knighthack an hour ago

      Try Nim's macros.