Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Zlodo
Nov 25, 2006

Share Bear posted:

Maybe I should stick to the terrible programmer thread

python chat belongs in both

Adbot
ADBOT LOVES YOU

VikingofRock
Aug 24, 2008




Share Bear posted:

OK so what is the preferred way to transform another class or dict or other list into a new list? I thought this was pretty snappy.

My read is that Xarn is saying that adding a comment explaining the list comprehension is terrible, not that the list comprehension itself is terrible.

Personally, I like list comprehensions so long as they don't get too complicated. I think a lot of times they are more readable and less error prone than the equivalent for loops. For example I'd much rather read

Python code:

valid_foos = [foo for foo in foos if valid(foo)]

than

Python code:

valid_foos = []
for foo in foos:
  if valid(foo):
    valid_foos.append(foo)

because to me the latter seems needlessly verbose and stateful

ynohtna
Feb 16, 2007

backwoods compatible
Illegal Hen
did you just tell me to go foo myself?

Cybernetic Vermin
Apr 18, 2005

i kind of like list comprehensions, but tbqh i don't think they improve on map/filter/fold-chains enough to be a real improvement. like, the natural language'y look they have is sort of pleasing and gives the *appearance* of being easier, but teaching python they didn't seem any less of a stumbling block, and it does amount to additional magical syntax.

Notorious b.s.d.
Jan 25, 2003

by Reene

VikingofRock posted:

My read is that Xarn is saying that adding a comment explaining the list comprehension is terrible, not that the list comprehension itself is terrible.

Personally, I like list comprehensions so long as they don't get too complicated. I think a lot of times they are more readable and less error prone than the equivalent for loops. For example I'd much rather read

Python code:
valid_foos = [foo for foo in foos if valid(foo)]
than

Python code:
valid_foos = []
for foo in foos:
  if valid(foo):
    valid_foos.append(foo)
because to me the latter seems needlessly verbose and stateful

i'd rather see

code:
valid_foos = foos.select ...
you know, like a sane language with higher-order functions

bonus points if it's typesafe, which python never is

brap
Aug 23, 2004

Grimey Drawer
I really enjoy the way python throws if you concatenate a number to a string as if this behavior is type safety

Zlodo
Nov 25, 2006
sometimes i visit amiga forums out of morbid curiosity and they have decided to reboot that video game making basic that existed back then but now it transpiles to javascript in case anyone wanted that

also apparently to do anything useful you have to inline some javascript anyway

"The simplicity of AMOS, the speed of Javascript!"

http://amos2.tech/Code-Showcase/Animated-Julia

http://amos2.tech/Code-Showcase/AMOS-Ball

im the Boob Set Hotspot

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



lol nice. I hosed around with a used* copy of Amos pro 4 back in the day

* yes, in the original box w manuals and all

Pie Colony
Dec 8, 2006
I AM SUCH A FUCKUP THAT I CAN'T EVEN POST IN AN E/N THREAD I STARTED

brap posted:

I really enjoy the way python throws if you concatenate a number to a string as if this behavior is type safety

smh that is type safety, if you want build-time type safety use python’s type checker

Pie Colony
Dec 8, 2006
I AM SUCH A FUCKUP THAT I CAN'T EVEN POST IN AN E/N THREAD I STARTED

Notorious b.s.d. posted:

i'd rather see

code:
valid_foos = foos.select ...
you know, like a sane language with higher-order functions

bonus points if it's typesafe, which python never is

lol, zero programming languages are sane, there’s just the set you know how to use and the set you don’t

VikingofRock
Aug 24, 2008




Notorious b.s.d. posted:

i'd rather see

code:
valid_foos = foos.select ...
you know, like a sane language with higher-order functions

bonus points if it's typesafe, which python never is

Yeah, agreed on that point. There is

Python code:

valid_foos = list(filter(valid, foos))

and frequently you can drop the list() call if you only need to iterate it once. I understand the motivation for making filter() a built-in instead of a member function for the different iterables, but I think I'd still prefer it as a member function in the end when possible.

Regardless, I was mostly responding to the idea that list comprehensions are bad python style or particularly hard to read, since I disagree with both of those notions.

animist
Aug 28, 2018

Pie Colony posted:

smh that is type safety, if you want build-time type safety use python’s type checker

which has no typings for 90% of the ecosystem :argh:

ErIog
Jul 11, 2001

:nsacloud:

VikingofRock posted:

Regardless, I was mostly responding to the idea that list comprehensions are bad python style or particularly hard to read, since I disagree with both of those notions.

I think the minimal example cases that get used to say, "See! List comprehensions are so easy!" are a bad framing of the problem because that's not really what people are complaining about when they say they're complicated. In isolation, a simple list comprehension is fine. However, when you extend it even slightly with multiple for statements, complicated anonymous functions, or functions with non-obvious purpose it degenerates very quickly. For the simplest cases list comprehensions are easier to understand than their equivalent expanded for loop versions. However, for the more complicated cases the list comprehensions just become a kind of terse obfuscation.

The other thing which also maybe happens is that the list comprehensions get out of hand over time rather than all at once. Somebody thinks what they're doing is fundamentally simple and very obvious so they use a simple list comprehension, but then the list comprehension gets more and more complicated as the developer modifies it to meet the more complicated needs as they realize they have them. The developer, at that point, probably should just replace it with some for loops to spread the complexity out over more lines with more opportunities for helpful comments. However, when working on code people often just go with inertia, making modifications to code rather than rewriting or restructuring it.

In a world where developers are very good and mindful about writing readable code list comprehensions would be fine, but in practice it seems like they're yet another case of a Python feature that makes it easier to write bad code than good code.

Progressive JPEG
Feb 19, 2003

Pie Colony posted:

smh that is type safety, if you want build-time type safety use python’s type checker

but I thought the whole point of PLs was to shift as many errors as possible into run time?

Progressive JPEG
Feb 19, 2003

I mean why use a PL if you aren't going to leave little typing time bombs strewn throughout your code?

theodop
Dec 30, 2005

rock solid, heart touching

ErIog posted:

I think the minimal example cases that get used to say, "See! List comprehensions are so easy!" are a bad framing of the problem because that's not really what people are complaining about when they say they're complicated. In isolation, a simple list comprehension is fine. However, when you extend it even slightly with multiple for statements, complicated anonymous functions, or functions with non-obvious purpose it degenerates very quickly. For the simplest cases list comprehensions are easier to understand than their equivalent expanded for loop versions. However, for the more complicated cases the list comprehensions just become a kind of terse obfuscation.

The other thing which also maybe happens is that the list comprehensions get out of hand over time rather than all at once. Somebody thinks what they're doing is fundamentally simple and very obvious so they use a simple list comprehension, but then the list comprehension gets more and more complicated as the developer modifies it to meet the more complicated needs as they realize they have them. The developer, at that point, probably should just replace it with some for loops to spread the complexity out over more lines with more opportunities for helpful comments. However, when working on code people often just go with inertia, making modifications to code rather than rewriting or restructuring it.

In a world where developers are very good and mindful about writing readable code list comprehensions would be fine, but in practice it seems like they're yet another case of a Python feature that makes it easier to write bad code than good code.

if I had a code review and it had LINQ which was more complicated than butts.Where(butt -> butt.HasFart).OrderBy(butt -> butt.Size).ToArray() I would fail it and ask for every chained function to be split out to its own variable. Forcing people to name the variables means 1) they have to think about what each step is actually achieving and 2) it implicitly documents it. it's harder to do the same thing with their bizarre list comprehension syntax but fortunately nobody uses that in .NET.

I've seen too many monstrosities that chain together 5-10 filters and maps and just because they've used line breaks doesn't make it less of an assache to troubleshoot

Share Bear
Apr 27, 2004

theodop posted:

if I had a code review and it had LINQ which was more complicated than butts.Where(butt -> butt.HasFart).OrderBy(butt -> butt.Size).ToArray() I would fail it and ask for every chained function to be split out to its own variable. Forcing people to name the variables means 1) they have to think about what each step is actually achieving and 2) it implicitly documents it. it's harder to do the same thing with their bizarre list comprehension syntax but fortunately nobody uses that in .NET.

even though ive been championing list comps, 100% this

“clever” or “clean” code is usually worse than either explicit poo poo or “clever” poo poo with comments

luchadornado
Oct 7, 2004

A boombox is not a toy!

adding comments to poo poo code just means its poo poo code with comments

Notorious b.s.d.
Jan 25, 2003

by Reene

VikingofRock posted:

and frequently you can drop the list() call if you only need to iterate it once. I understand the motivation for making filter() a built-in instead of a member function for the different iterables, but I think I'd still prefer it as a member function in the end when possible.

focusing on built-in vs member function misses the forest for the trees

the problem is that python treats higher-order functions as "un-pythonic" and doing super basic poo poo that is trivial in c# or java requires you to jump through dumb hoops

even ruby and perl do this better. (not that it matters, because ruby and perl are terrible.)

Share Bear
Apr 27, 2004

Helicity posted:

adding comments to poo poo code just means its poo poo code with comments

explicit poo poo is better than poo poo with nothing going for it, because not ever org has time to refactor

comments are usually good

pragmatism not idealism, will not cry in public

Share Bear
Apr 27, 2004

everyone's pretending they're not constantly turning out poo poo that sucks, because their poo poo that sucks is better than other people's poo poo that sucks

addressing that all this poo poo sucks is worse than being quiet

Pie Colony
Dec 8, 2006
I AM SUCH A FUCKUP THAT I CAN'T EVEN POST IN AN E/N THREAD I STARTED

Notorious b.s.d. posted:

focusing on built-in vs member function misses the forest for the trees

the problem is that python treats higher-order functions as "un-pythonic" and doing super basic poo poo that is trivial in c# or java requires you to jump through dumb hoops

even ruby and perl do this better. (not that it matters, because ruby and perl are terrible.)

what exactly are you complaining about? what is trivial in java that requires dumb hoops in python, or are you saying list comprehensions are dumb hoops?

no one is saying you have to write your python code any certain way. you can still use the built-in functions or the functools module. but like all functional code, it'll be slower than the alternative

Pie Colony
Dec 8, 2006
I AM SUCH A FUCKUP THAT I CAN'T EVEN POST IN AN E/N THREAD I STARTED
the python defender has logged on

Notorious b.s.d.
Jan 25, 2003

by Reene

Helicity posted:

adding comments to poo poo code just means its poo poo code with comments

poo poo code with detailed comments is better than poo poo code without detailed comments

but...

if you know you are doing something tricky and hard to understand, maybe you should try and make it simpler?

Pie Colony
Dec 8, 2006
I AM SUCH A FUCKUP THAT I CAN'T EVEN POST IN AN E/N THREAD I STARTED
drat i wrote some dumb poo poo in python when i was in undergrad

code:
def curry(x, c=None):
    if c is None:
        c = x.func_code.co_argcount
    x.__curried = True
 
    def p(*a):
        if len(a) > c:
            f = x(*a[:c])
            if getattr(f, '__curried', False):
                f = curry(f)
            return f(*a[c:])
        elif len(a) == c:
            return x(*a)
 
        def q(*b):
            return x(*(a + b))
 
        q.__name__ = p.__name__[:-3] + ' -> '.join([''] + [str(b) for b in a])
        return curry(q, c - len(a))
   
    p.__name__ = '%s...' % x.__name__
    return p
 
>>> id = curry(lambda x: x)
>>> const = curry(lambda x, y: x)
>>> const(3)
<function <lambda> -> 3... at 0x106e97a28>
>>> _(4) == const(3,4)
True
>>> comp = curry(lambda f, g: lambda x: f(g(x)))
>>> id(comp, lambda x: x + 2, lambda x: x * 4, 100)
402
is this python or haskell? you can't even tell the difference. i also implemented tail call optimization

mystes
May 31, 2006

Python gets pretty unreadable when you try to do stuff like that. Also, isn't that just partial application rather than currying?

mystes fucked around with this message at 02:52 on Jul 12, 2019

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
drat, imagine worrying about making your python code slow

Pie Colony
Dec 8, 2006
I AM SUCH A FUCKUP THAT I CAN'T EVEN POST IN AN E/N THREAD I STARTED
no you see, modifying your functions' ASTs at runtime actually makes them better

code:
from ast import *
from inspect import getsource

class TrampolineTransform(NodeTransformer):
    def visit_Return(self, node):
        return_val = node.value

        if return_val.__class__ == Call:
            func = return_val.func
            func_args = return_val.args
            return copy_location(Return(
                value=Tuple(elts=[
                    Str(s='__trampoline'), 
                    func, 
                    List(elts=func_args, ctx=Load())
                ], ctx=Load()), ctx=Load()
            ), node)

        return node


def trampoline(start):
    ret = start()
    while isinstance(ret, tuple) and ret[0] == '__trampoline':
        _, func, args = ret
        ret = func(*args)
    return ret


def odd(n):
    if n == 1: return True
    return even(n-1)


def even(n):
    if n == 1: return False
    return odd(n-1)


def compile_tco(f):
    ast = parse(getsource(f))
    tco_ast = fix_missing_locations(TrampolineTransform().visit(ast))
    return compile(tco_ast, __name__, 'exec')

exec compile_tco(odd)
exec compile_tco(even)

>>> print trampoline(lambda: even(59392))
True

Pie Colony fucked around with this message at 03:34 on Jul 12, 2019

Lutha Mahtin
Oct 10, 2010

Your brokebrain sin is absolved...go and shitpost no more!

Nomnom Cookie posted:

isnt that perl. p sure i even read a quote some years back from larry wall about how he tried to make writing perl similar to a natural language--highly contextual, sometimes ambiguous, but expressive

one of the big choices of larry wall's life was when he decided between (a) designing a computer language, or (b) moving to a remote tribal area of the world, learning the language, creating a script for it, and translating the Bible into it (he's Church of the Nazarene). he chose (a) and the rest of us get to deal with it lol

brap
Aug 23, 2004

Grimey Drawer

Pie Colony posted:

smh that is type safety, if you want build-time type safety use python’s type checker

it's not type safety, it's just a limitation. look at how any other language handles the scenario of `someString + someNumber`. it's a matter of what combinations of operand types are supported. python just made a choice that results in crappy ergonomics in practice.

mystes
May 31, 2006

It's reasonable not to allow that for type safety but it makes less sense in a language where you can multiply strings by numbers.

Kazinsal
Dec 13, 2011


mystes posted:

It's reasonable not to allow that for type safety but it makes less sense in a language where you can multiply strings by numbers.

imo if "yospos" * 3 = "yosposyosposyospos" then "yospos" + 4 should = "yosposyosp"

Nomnom Cookie
Aug 30, 2009



mystes posted:

It's reasonable not to allow that for type safety but it makes less sense in a language where you can multiply strings by numbers.

you can also multiply lists by numbers

I’ve done this in production code

it made me feel dirty

cinci zoo sniper
Mar 15, 2013




Pie Colony posted:

no you see, modifying your functions' ASTs at runtime actually makes them better

code:
from ast import *
from inspect import getsource

class TrampolineTransform(NodeTransformer):
    def visit_Return(self, node):
        return_val = node.value

        if return_val.__class__ == Call:
            func = return_val.func
            func_args = return_val.args
            return copy_location(Return(
                value=Tuple(elts=[
                    Str(s='__trampoline'), 
                    func, 
                    List(elts=func_args, ctx=Load())
                ], ctx=Load()), ctx=Load()
            ), node)

        return node


def trampoline(start):
    ret = start()
    while isinstance(ret, tuple) and ret[0] == '__trampoline':
        _, func, args = ret
        ret = func(*args)
    return ret


def odd(n):
    if n == 1: return True
    return even(n-1)


def even(n):
    if n == 1: return False
    return odd(n-1)


def compile_tco(f):
    ast = parse(getsource(f))
    tco_ast = fix_missing_locations(TrampolineTransform().visit(ast))
    return compile(tco_ast, __name__, 'exec')

exec compile_tco(odd)
exec compile_tco(even)

>>> print trampoline(lambda: even(59392))
True

you will face the court of code for your crimes

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde
e: wrang thad

Gazpacho fucked around with this message at 07:07 on Jul 12, 2019

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



Kazinsal posted:

imo if "yospos" * 3 = "yosposyosposyospos" then "yospos" + 4 should = "yosposyosp"

checks out

eschaton
Mar 7, 2007

Don't you just hate when you wind up in a store with people who are in a socioeconomic class that is pretty obviously about two levels lower than your own?
if only python had something simple and readable like the Common Lisp LOOP macro

Xarn
Jun 26, 2015

Kazinsal posted:

imo if "yospos" * 3 = "yosposyosposyospos" then "yospos" + 4 should = "yosposyosp"

Progressive JPEG
Feb 19, 2003

Nomnom Cookie posted:

you can also multiply lists by numbers

I’ve done this in production code

it made me feel dirty

python in production? oof

Adbot
ADBOT LOVES YOU

Progressive JPEG
Feb 19, 2003

Pie Colony posted:

the python defender has logged on

does python still have that thing where input written by a foreigner suddenly triggers a requirement to blindly add .decode("utf8") to everything until the errors go away?

it's so type safe that some strings are differently typed from other strings

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply