- version control - while developing a program I create multiple versions. Development may split into multiple paths or be backtracked. Without proper version control, confusion is inevitable.
- illegible code - I make frequent tweaks and changes, use irrelevant names for labels and functions and fail to comment code. It's unlikely I'll understand the program if I return to it a few weeks later.
Earlier this week I posted an example of ugly code. By examining the program, the magic numbers or output for sample input, three readers identified the code as an implementation of parallel bit counting. Here's how the bit counter ought to have been implemented:
: (COUNTBITS) ( u1 u2 u3 -- u4 ) ( u1 = partial count ) ( u2 = power ) ( u3 = mask ) ( u4 = new partial count ) ROT 2DUP AND >R ROT / AND R> + ; : COUNTBITS ( u1 -- u2 ) ( parallel count ) ( u2 = number of 1 bits in u1 ) 2 %101010101010101 (COUNTBITS) 4 %011001100110011 (COUNTBITS) 16 %000011100000111 (COUNTBITS) 256 %000000000001111 (COUNTBITS) ;
To increase code legibility, the following changes have been made:
- function name now represents the word's behaviour
- word factored into two simpler words
- documented the word's stack activity
- represented the bit masks in binary
It's also worth considering what
countbits
will be used for (any suggestions?). Do we really need a fast bit twiddling algorithm? A simple iterated count or sparse ones algorithm will probably suffice:: COUNTBITS ( u1 -- u2 )( iterated count ) ( u2 = number of 1 bits in u1 ) 0 SWAP BEGIN 2 /MOD >R + R> ?DUP 0= UNTIL ;
: COUNTBITS ( u1 -- u2 ) ( sparse ones ) ( u2 = number of 1 bits in u1 ) 0 SWAP BEGIN ?DUP WHILE DUP 1- AND >R 1+ R> REPEAT ;