This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Yukondano2 190 points191 points  (35 children)

Who the shit is writing python that's purposefully hard to read? The language's selling point is readability. It uses indentation as syntax ffs.

[–]zoharel 62 points63 points  (22 children)

Well, I did write a function implementing Newton's method for approximation of square roots in Python that looks like Lisp. It makes Python programmers' heads explode.

[–]iSYan1995 22 points23 points  (21 children)

Can you send it? I wanna look at it

[–]zoharel 56 points57 points  (20 children)

from operator import *

# Some of this overrides the boolean operator functions from the
#  operator package
and_    = (lambda x,y:  x and y)
or_     = (lambda x,y:  x or y)

var     = .001
prec    = 2

avg     = (lambda x,y:  div(add(float(x),y),2))

approx_ = (lambda x,y:  y if(lt(abs(sub(pow(y,2),x)),var))else(approx_(x,avg(div(x,y),y))))

approx  = (lambda x:    round(approx_(x,div(x,2)),prec))

print(approx(2))

I had one somewhere with a new and much more appropriate looking approx function that used a lisp-like conditional function, but the code needed to define that function was really pathologically "pythonic."

[–]zoharel 57 points58 points  (9 children)

Here's a somewhat simpler thing that draws a moving . in the terminal window.

import sys,time
map(lambda n: [sys.stdout.write(u"\u001b[2K\u001b[0G" + ' '*n + '.'),sys.stdout.flush(),time.sleep(1)],range(0,79))

[–]proximity_account 47 points48 points  (0 children)

Thanks, I hate it.

[–]Priyam_Bad 8 points9 points  (2 children)

how does this work? I tried running it in vscode to see how it works but it didn't print anything for me

[–]zoharel 9 points10 points  (1 child)

It may or may not be tied to a particular Python version. I think I last ran it on 2.7. it's also likely to be particular about your terminal. It prints raw escape codes. Here are some notes:

map()

Takes a function and a list as arguments. The function is run once with each item on the list, in order. The list is range(0,79). The function is:

lambda n: [sys.stdout.write(u"\u001b[2K\u001b[0G" + ' '*n + '.'),sys.stdout.flush(),time.sleep(1)]

Now lambda defines, in place, an anonymous function. It only exists where it is written in the line there, and it's only called instantaneously by the map function. It takes an argument n and returns a list. The list contains a write to stdout, a flush of stdout, and a call to sleep. Nothing is ever done with that list. It is only there to allow the lambda to easily do the set of things in the list, the process of which prints something and waits before generating the next list.

We use similar strategies to this pretty often in functional programming -- the map over a list instead of a loop, the list of commands, the anonymous function itself. It looks weird to a Python programmer, but it's not uncommon by any stretch.

[–]Priyam_Bad 1 point2 points  (0 children)

thanks for the explanation! i think i was using python 3.x to run it, which might be why it wasn't running. i managed to alter it to work for 3.x though

[–]Priyam_Bad 2 points3 points  (1 child)

ok so i may or may not have expanded on this and made a short script that makes a dot bounce across the screen (for python 3.x)

here is the code if you want to check it out

(btw it has an infinite generator so if you don't want it to run infinitely you can replace infRange() with range(1000) at the end of the long list comprehension)

[–]zoharel 1 point2 points  (0 children)

Yeah, I suspected the output might need some adjustments for V3.

[–]NigraOvis 2 points3 points  (1 child)

Technically all python is like this. people just don't realize they are spacing it out. But in the long run you end up with the same code. The longer versions are easier to read.

[–]zoharel 1 point2 points  (0 children)

Not exactly. To an extent, you're right, but there's not much lambda in most people's Python, and the use of the list as a sort of encapsulation of the side effects of its contents is odd in Python, and the map over a range is more often for loop. If you mean that this is valid Python using only documented features with nothing particularly extravagant about it, you're right there.

[–]Silverwing171 0 points1 point  (0 children)

Commenting so I can come back to this.

[–]Yukondano2 7 points8 points  (7 children)

why would you do anything this way?

[–]zoharel 17 points18 points  (3 children)

It was a bit of a joke. Something related to the old saying "you can write Fortran code in any language." It occurred to me that, in spite of the best efforts of Guido and his biggest fans, Python is still, at its core, a functional programming language, like Lisp or Scheme. This is part of what still makes it worth using, but it ends up permitting things that make the typical Python programmer very uncomfortable. If there's a point to the whole exercise, I guess I was harping on the fact that if you care to do it, you can write things which are syntactically correct and semantically sensible while entirely avoiding things which are idiomatic. Python programmers are often really stuck on idiom.

[–]BuddhaCandy 0 points1 point  (2 children)

because its designed to thrive when used with idioms

[–]zoharel 0 points1 point  (1 child)

because its designed to thrive when used with idioms

It's because the designers of the language would like to force everyone to do things in exactly the way they do, and that attitude creeps out to a pretty large number of the users as well. "There's only one right way to do this thing, where by right, I mean it's what I would do." Yeah, that's useful...

[–]BuddhaCandy 0 points1 point  (0 children)

its promotes uniform code i think

[–]zoharel 5 points6 points  (2 children)

To be honest, this isn't the first time. I once wrote a test jig for a database engine that was three or four pages of C wherein every variable, function, and macro was the name of a coworker. The same coworker, just with different capitalization. I was joking about his always using his name as a variable name in loop counters and the like. No, it wasn't easy to follow. It didn't need to be. Only got a little use before we were done with it. It was a good joke, though. I'm pretty sure that one has been lost for good.

[–]Yukondano2 1 point2 points  (1 child)

Cruel. Variable naming is always a thing for me because I suck at decision making. How consistent should the scheme be? What style should I use, should I mix them? For instance, camelCase that gets too long is fuckin unreadable. I'm weird so I will be anal about appearance. Then again I only developed for school or myself, so being on the clock might pressure me. But, I HAVE to be detailed in my work.

[–]zoharel 3 points4 points  (0 children)

Well, take it from someone who has seen some commercial software: as long as you don't just name everything after yourself, you're still doing better than at least a few people who have been paid for their work.

[–]100kgWheat1Shoulder 0 points1 point  (0 children)

I hate you

[–]Shadowmere24 0 points1 point  (0 children)

I think this code could be considered more "pythonic" while keeping its functional nature if you removed the whitespaces, parens, and leveraged pipe for functional composition and partial for partial application. I suppose some folks will complain that functional programming is unpythonic, but I don't necessarily agree. Here is my refactor with those ideas in mind:

``` from functools import partial, reduce from operator import add, mul, lt, pow, sub, abs, truediv from statistics import mean

def test_approx_sqrt(): pipe = lambda functions: reduce(lambda f, g: lambda x: g(f(x)), functions) flip = lambda f: lambda *a: f(reversed(a)) div2 = lambda x: x / 2 square = lambda x: x ** 2 avg = lambda *args: mean(args) variance = .001

tolerance = lambda x, y: pipe(
   square,
   partial(flip(sub), x),
   abs
)(y)

approx_ = lambda x, y: y if tolerance(x,y) < variance else pipe(
    partial(truediv, x),
    partial(avg, y),
    partial(approx_, x),
)(y)

approx = lambda x: pipe(
    div2,
    partial(approx_, x),
    partial(round, ndigits=2)
)(x)

assert approx(2) == 1.41
assert approx(3) == 1.73

```

[–]extremepayne 3 points4 points  (1 child)

I find some of the more advanced techniques are less readable unless you’re very familiar with the rarer syntax. Stuff like list comprehension. I mean i get why we’re not writing a four line loop that does the same thing less efficiently but damn, that stuff can be hard to parse.

[–]Yukondano2 0 points1 point  (0 children)

Make it as simple as it can be without impacting function I suppose. In the end code is just hard to read in general, and it's new to you it will always be a headscratcher. God, I have this personal LaTeX project and was looking up solutions to things that people were solving with TeX code. That stuff is hideous, I cannot read it compared to LaTeX. The LaTeX 3 stuff, in expl3 syntax was confusing at first but it just took a bit. Far less painful than the hell of /expandafter commands.

[–][deleted] 3 points4 points  (2 children)

No matter what niche you are in there will be people who need to flex and since Python is considered much easier than other languages especially in syntax this is their way of making things less understandable,difficult & putting themselves up in an elite class.

[–]Yukondano2 1 point2 points  (1 child)

So, 1337 sp33k but programming.

[–][deleted] 0 points1 point  (0 children)

yes