Anti-pattern of the Week

jpmay's picture

I recently ran into an interesting twist on the infamous Maple anti-pattern:

# A very garbagey way to build a list
l := [];
for i from 1 to 10000 by 100 do
    l := [op(l), isqrt(abs(floor((5000-i)/2)))];
end do;

A lot of users fall prey to this method of building a list rather than using seq:

# generate a list without extraneous garbage
l := [seq(isqrt(abs(floor((5000-i)/2))),i=1..10000,100)];

So, now the twist. The same problem can also crop up in taking a list apart.

# A very garbagey way to find the min in a list
while nops(l) > 1 do
    if l[1] > l[2] then
	l := subsop(1=NULL, l);
    else
        l := subsop(2=NULL, l);
    end if;
end do;
op(l);

Upon first glance this code is pretty clever, but in fact, it has exactly all the bad features of constructing a list in a loop, namely, for a list of length n, the loop uses n^2 memory. In this case, the boring method is much better:

# find the min without extra garbage
m := l[1];
for i in l do
    if m > i then
	m := i;
    end if;
end do;
m;

Of course, you should really use min, but in this case the user was implementing min with a custom comparator like the two argument version of sort.

These code snippets are also good arguments for programming in a font that allows one to distinguish between 1, l, and i (and I and |) at glance. (Bad even in <tt> for my browser font: 1,l,i,I,| )

}