Hacker News new | past | comments | ask | show | jobs | submit login
Adding syntax to the CPython interpreter (leontrolski.github.io)
70 points by leontrolski 6 hours ago | hide | past | favorite | 25 comments





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

So if "else None" is omitted, if bar is false, then does spam == None or is it unmodified? The former is what I think you want, but that would be very confusing.

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

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


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.


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

there is a nice "staticscope" package in python, which acts as a context manager, and does pretty much what you refer to. pretty neat.

https://pypi.org/project/scoping/


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))

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


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

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


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?

Great post!

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

https://github.com/pkolchanov/CustomizingPython


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

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

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.


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

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.


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!


It's specified in PEP 263 [0] which pulls up easier on search if you quote it and include the typical "special comment symbol" -*- around it.

[0]: https://peps.python.org/pep-0263/


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


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.


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


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

Try Nim's macros.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: