-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathwhy-is-potato-programming-bad.txt
93 lines (73 loc) · 2.59 KB
/
why-is-potato-programming-bad.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
= 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:
{{{
#!python
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:
{{{
#!python
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:
{{{
#!python
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:
{{{
#!python
def axiom_users(s):
for u in s.query(User):
if u.uid < 1000:
yield u.name
}}}
vector style:
{{{
#!python
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.
In fact, in this case, we can push the loop further down into Axiom:
{{{
#!python
def axiom_users(s):
return s.query(User, User.uid < 1000).getColumn('name')
}}}