
Convert any Python file into a single line of code - odeke-em
https://github.com/csvoss/oneliner
======
dahart
+1 for the amusing faq. And I think this is a cool project. I'll use it just
to learn better ways to make one-liners for use in other shell scripts and
makefiles. Python has always been harder than the other languages I know to
make one-liners, but on occasion it's quite useful.

~~~
mrks_
On what occasion would a one-liner be useful? I'm genuinely curious, because I
can't think of any such case, but I wouldn't doubt there being a few.

~~~
gknoy
Command line use. You grep some files, and think, "man, this really needs this
ONE LITTLE FILTER". So, you pipe it to `perl -e "..."`, and soon have a very
short program that you iterate on a few times to make sure you have right, and
then you pipe it through the rest of the toolchain.

I don't write Perl much anymore, but that was far and away my __favorite__ way
to use it. I love coding in Python now, more than I ever liked programming in
any language (except perhaps lisp), but I still don't feel I can use it on the
command line that way.

In the context of a Python program, I can't see the value of a Lovecraftian
lambda (unless maybe in code golf comments?), but I found this article very
appealing mainly because it's quite a feat. Doing anything nontrivial in a
lambda is a pain in the ass, so the fact that someone wrote a tool to do it is
awesome.

------
detaro
For a very limited definition of "any python file".

Still brings me back to highschool, where we toyed with that kind of tricks
(someone builds something, the others try to figure out how it works). Fun
times!

~~~
raverbashing
Yeah, like trying to do a C file without semicolons

------
kosievdmerwe
I in the distant past when I was still in Uni attempted to do something
similar, though I never finished it. I think I should take up my project again
and try to finish it this time. I got stuck last time trying to figure out how
to do a try/catch.

The one big thing I notice this is doing "wrong", is that it is not linear in
recursion depth: Each statement increases the stack depth by 1. The way around
this is to instead sequence the commands using arrays, since python guarantees
the execution order is left to right. So his example could have been rewritten
as:

    
    
      (lambda s: [s.__setitem__('x', 3), s.__setitem__('y', 4), print(s['x'] < s['y'] < 5)])({})
    

(though for this example you could just modify the result of globals())

Then you can also do trickery to get for and while loops into generator
expressions as opposed to lambdas. The hard part is handling continues and
breaks. For instance:

    
    
      while <cond>:
        <stmts>
    

can get compiled into something like

    
    
      list(<compiled_stmts> for _ in itertools.takewhile(lambda _: <compiled_cond>, itertools.cycle([1])))
    

(though you'll want to replace list with a function that evaluates the
iterator but doesn't take up O(N) space where N is the number of iterations,
something like a no-op accumulator)

To handle breaks and continues, you'd have to make your <compiled_stmts> be
aware that a break/continue was called (a flag on some meta table was my
plan), so they can terminate early. You'd also have to change <compiled_cond>
to terminate the loop (on a break) and reset the continue flag.

------
htor
Nice.

This made me think of this video with Jim Weirich demonstrating functional
patterns, transformations and the Y combinator:

[https://vimeo.com/45140590](https://vimeo.com/45140590)

Highly recommened. It's very related to what seems to be going on here, and
actually quite funny.

------
rplnt
> Your code was not valid: 'try-except' is an open problem.

Well that was disappointing...

------
vldr
First try: Your code could not be one-lined. Open problem: try-except

Second try: Your code could not be one-lined. Open problem: yield

Third try: Your code could not be one-lined. Open problem: raise

Fourth try: Your code could not be one-lined. Not yet implemented: classdef

So, any file without class definitions, try/except/raise/yield (and probably
some more). Not my definition of 'any' :)

------
amelius
> However, since while loops and for loops are implemented with recursion, you
> might encounter maximum recursion depth exceeded errors during runtime if
> your loops go on for too long.

Okay, this was enough to scare me away from it :)

------
phantom_oracle
_Why pass up a perfectly good excuse to abuse lambda functions, ternary
expressions, list comprehensions, and even the occasional Y combinator? Never
pass up an opportunity to use the Y combinator._

^^ Legendary

------
im3w1l
I formatted one of the converted examples for easier reading

[http://pastebin.com/SEMHXkd6](http://pastebin.com/SEMHXkd6)

------
benzoate
Call me when the results are compliant with PEP8

~~~
StavrosK
Brrring

~~~
benzoate
haha, I think the resulting one liners are a little over 80 characters :)

~~~
StavrosK
Eh, you can insert newlines wherever you want and it'll still work, plus the
"80 char line" rule is at the top of the list of PEP8 rules you can break.

~~~
benzoate
True, but then it's not on one line anymore, and the code likely ends up on
more lines. If only there was some other version of the code that took up less
lines and characters... :)

------
wfunction
> Space: O(n). No code is ever duplicated, so the one-lined code produced is
> linear in the size of the input code.

Seems like a non sequitur?

~~~
philh
I'm not sure why you think that. Do you mean that normally, in this context
"space" means the memory usage of a program, which isn't particularly related
to the size of the program?

In which case, yeah, it's a little incongruous. The "space" bit is talking
about the textual representation of the program produced, while the "time" bit
is talking about the runtime characteristics of the program.

~~~
csvoss
Oh, you're right, I'm using "space" incorrectly. Fixed :)

------
enesunal
+1 for Y Combinator :)

------
wiz21
is it me or is it continuation passing style ?

------
cmdrfred
Import pythonfile

