Bare words / new keywords in Python
Asked Answered
W

1

27

I wanted to see if it was possible to define new keywords or, as they're called in Destroy All Software's "WAT" talk when discussing Ruby, bare words, in Python.

I came up with an answer that I couldn't find elsewhere, so I decided to share it Q&A style on StackOverflow.

Winebaum answered 7/4, 2015 at 13:31 Comment(6)
Does anyone care to explain why they're downvoting/voting to close? I'm sharing knowledge that could be useful for anyone looking to add new keywords in Python without having to actually modify the interpreter's source code and recompile it. Could this be misused? It almost certainly will be. But if you really want to do it, then I have provided this here for you. And if you don't want to do it, then just move along - there's no need to downvote or to vote to close.Winebaum
An interesting use case for this would be implementing an interactive command line interface without input(). That way, you have the full power of an interactive shell and a cli at the same time. It is an anti-pattern, but it is interesting.Henke
You're too far ahead of the curve: that's why... ;-) It's not by inventing a tablet that you'll make money but by refining it and calling it an iPad that you will, so 1 up-vote (which will counteract 5 down-votes) >:-)Martinic
Gaze too long into the abyss, and the abyss gazes into you.Fein
I was thinking about that talk and googled "bare words programming" to find out what was being quickly mentioned and then passed by. This was the first result. (also glad so didn't close a helpful question)Phelgen
Hey!! I am here for the same reason. We are all de same 😭. All f*** nerds.Wattenberg
W
28

I've only tried this in the REPL, outside any block, so far. It may be possible to make it work elsewhere, too.

I put this in my python startup file:

import sys, traceback

def bareWordsHandler(type_, value, traceback_):
    if isinstance(value, SyntaxError):
        import traceback

        # You can probably modify this next line so that it'll work within blocks, as well as outside them:
        bareWords = traceback.format_exception(type_, value, traceback_)[1].split()

        # At this point we have the raw string that was entered.
        # Use whatever logic you want on it to decide what to do.
        if bareWords[0] == 'Awesome':
            print(' '.join(bareWords[1:]).upper() + '!')
            return
    bareWordsHandler.originalExceptHookFunction(type_, value, traceback_)

bareWordsHandler.originalExceptHookFunction = sys.excepthook
sys.excepthook = bareWordsHandler

Quick REPL session demonstration afterwords:

>>> Awesome bare words
BARE WORDS!

Use responsibly.

Edit: Here's a more useful example. I added in a run keyword.

if bareWords[0] == 'from' and bareWords[2] == 'run':
        atPrompt.autoRun = ['from ' + bareWords[1] + ' import ' + bareWords[3].split('(')[0],
                            ' '.join(bareWords[3:])]
        return

atPrompt.autoRun is a list of variables that, when my prompt is displayed, will automatically be checked and fed back. So, for example, I can do this:

>>> from loadBalanceTester run loadBalancerTest(runJar = False)

And this gets interpreted as:

from loadBalancerTest import loadBalancerTest
loadBalancerTest(runJar = False)

It's kind of like a macro - it's common for me to want to do this kind of thing, so I decided to add in a keyword that lets me do it in fewer keystrokes.

Winebaum answered 7/4, 2015 at 13:31 Comment(13)
@Fein I think these kinds of things are where new languages are born from. You do evil ugly things in existing languages, until eventually you decide to turn it into its own new official language. IE, I've heard C++ started life as a bunch of macros to make OO design easier in C.Winebaum
This is my favourite SO answer. This is such an abuse of an otherwise sensible and syntactically strict language, +1Sentience
@Sentience - Thanks. I'm glad I didn't give into peer-pressure and delete this when the initial reaction was all negative (the question got downvoted 5 times and the answer 3 times, all within a few hours of me posting it. Took several months for them to actually get positive scores.)Winebaum
In all honestly, I was browsing the bareword tag and saw this one, and I was prepared for a VLQ question from a Python newbie, but I'm impressed. Imma go scatter this throughout my company's codebase.Sentience
@Sentience - If you insist on doing that, please make sure that it's well documented... future maintainers will hate you if you do this and don't document it.Winebaum
Nahh, documentation's for chumps :P they can figure it out! I believe in them.Sentience
A little trolling does everyone a little good... especially when I don't actually have any company's codebase to mess with (unfortunately) :DSentience
So you can execute but not return from your bareword handler? So you can't implement operators like "not" or "is"? (took already existing operator, no inspiration for easy to understand usefull new ones þ)Armagnac
@JulienPalard - The entire line will come back to you. You can scan for your new keyword, then run everything on the left through exec to have the normal Python interpreter run that, then do the same with everything on the right, then combine the two results however you like.Winebaum
@JulienPalard - If you wanted to make it "return" something you could fake that... You could inject the results into a global variable, then run exec on the original line with the proper part replaced by the name of that global variable. Post as a new question if you're having problems trying this.Winebaum
Hey my comment got deleted at some point! (I basically said it was Evil, and I probably also said I loved it). Maybe a bot that doesnt understand programmers use the word "Evil" differently to other folksFein
I should note this doesnt work in python 3. If anyone has a work around , I'm all ears. EVIL EARS.Fein
@Fein - My example was missing import traceback and also had a typo in the name of the function. I fixed both issues and found it still works fine for me in the Python 3.8.5 interactive shell on macOS.Winebaum

© 2022 - 2024 — McMap. All rights reserved.