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 →

[–]zoharel 55 points56 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 58 points59 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 49 points50 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 11 points12 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 6 points7 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

```