Why is potato programming a bad idea? It seems normal to me.

Here is an expanded realistic potato/non-potato comparison, reading a list of system users.

Potato:

def system_users():
    lines = file('/etc/passwd').readlines()
    for line in lines:
        if len(line[:line.find('#')].strip()):
            fields = line.split(':')
            if int(fields[2]) < 1000:
                yield fields[0]

timeit.py result: 100000 loops, best of 3: 187 usec per loop

Vector:

import pwd
import operator
def system_users():
    users = pwd.getpwall()
    users.sort(key=operator.itemgetter(2))
    for user in users:
        if user[2] < 1000:
            yield user[0]
        else:
            return

100000 loops, best of 3: 137 usec per loop

Now, you might say, "That's not a fair comparison! The "VectorProgramming?" example is using a library for this while PotatoProgramming is implementing it from scratch!"

The comparison still holds, however:

import operator

def my_getpwall():
    lines = file('/etc/passwd').readlines()
    for line in lines:
        uncommline = line[:line.find('#')].strip()
        fields = uncommline.split(':')
        yield fields

def system_users():
    users = list(my_getpwall())
    users.sort(key=operator.itemgetter(2))
    for user in users:
        if user[2] < 1000:
            yield user[0]
        else:
            return

10000 loops, best of 3: 168 usec per loop

In other words, if 'pwd' did not exist, it would be necessary to invent it. When you optimize your code, you don't want to do it across boundaries which require the caller to make loops; you want the interface to be expressive so that the loops can be optimized within your interface. For an extreme version of PP, implement readline yourself with a for c in string: if c == '\n'...

Ideally, you wouldn't even have to write the 'for user in users' loop yourself. For example, here's an Axiom snippet to do a similar thing implemented potato-style:

def axiom_users(s):
    for u in s.query(User):
        if u.uid < 1000:
            yield u.name

vector style:

def axiom_users(s):
    for u in s.query(User, User.uid < 1000):
        yield u.name

Axiom aims to force as much work down into the optimizeable guts of the library as possible, then use the interface that way, rather than doing additional iteration and testing in application code.

jethro@divmod.org