## Elements of SQR Style

*Elements of Style* is the famous book by William Strunk, Jr. and E.B. White. First written in 1918, it is a guide to writing well in American English. Anything good about the prose on this blog should be credited to Strunk & White. The flaws must be ascribed to me. This week’s blog entry is dedicated to that short book.

### Fortran Versus Cobol

I learned Basic, Assembly, Fortran, and Cobol in school, and I did far more development in Basic and Fortran than Assembly and Cobol. To me, it seemed easier and simpler to perform mathematical calculations with formulae (my spell checker objects to the Latin form), than to sequence each operation through a series of temporary variables. Consider the solutions to a quadratic equation.

`let #x1 = (-#b + sqrt(#b*#b – 4*#a*#c)) / (2*#a)`

let #x2 = (-#b - sqrt(#b*#b – 4*#a*#c)) / (2*#a)

versus

`move #b to #temp1`

multiply #b times #temp1

move 4 to #temp2

multiply #a times #temp2

multiply #c times #temp2

subtract #temp2 from #temp1

do square_root(#temp1, #x1)

move #x1 to #x2

subtract #b from #x1

divide 2 into #x1

divide #a into #x1

add #b to #x2

multiply -1 times #x2

divide 2 into #x2

divide #a into #x2

`procedure square_root(#input, :#divisor)`

move 1 to #divisor

while {true}

move #input to #dividend

divide #divisor into #dividend

add #divisor to #dividend

divide 2 into #dividend

subtract #dividend from #divisor

if #divisor > -.0001 and #divisor < .0001

break

end-if

move #dividend to #divisor

end-while

end-procedure

Did you recognize Isaac Newton’s method for square roots?

When I started programming in SQR, I adopted the **let** command and avoided the commands that reminded me of Assembly or Cobol; **add**, **subtract**, **multiply**, **divide**, and **move**. Even reading about the performance advantages of those commands couldn’t persuade me to use them.

Now I use them to communicate the intentions behind my arithmetic.

### The Subtext Of A Command

Psychologists say that most of what we communicate is non-verbal; our tone of voice, the cadence of our words, our facial expressions, and our body language. There is some of that in our programs; vertical spacing, horizontal spacing, and how we divide a command into multiple lines.

I would argue that our choice of commands can tell another programmer more than it tells the SQR compiler, if we make the choices consciously and consistently. Consider the characteristics of the **let** command versus the others (**add**, **subtract**, **multiply**, **divide**, and **move**).

- The
**let**command is followed immediately by – and highlights – a variable whose value is about to change. The other commands are followed immediately by – and highlight – a variable or literal whose value will stay the same. - The variable after the
**let**command can be a date, number, or string variable. The variable or literal after the**move**command can also be a date, number, or string. However, the variable or literal after the other commands is constrained by the command to be numeric. There are other data manipulations commands (**concat**,**encode**,**extract**,**find**,**lowercase**,**uppercase**,**string**, and**unstring**) that constrain their values to be strings. These commands emphasize the nature of the data. - After the equals sign, the
**let**command allows us to write complex formulae that could be the equivalent of many, many single operation commands. This suggests that there is always some potential for complexity, even if the formula happens to be simple. After the preposition keyword (**to**,**from**,**times**,**into**), the other commands limit us to a single variable. - The
**let**command says “anything can happen.” Perhaps #x equals #x + 1 today, but we might change the program to set #x to 3.14159 * #r * #r tomorrow. If we make it our practice, the other commands can suggest stability in our algorithms. - The
**let**command can replace any of the other commands we’ve mentioned, and in other languages it can or must be omitted. It doesn’t really tell us or highlight anything about the calculation to follow. The other commands define the calculation and limit the syntax of the rest of the command.

### Initializing Variables

Initializing a variable is just one example of setting its value. The compiler doesn’t treat the command any differently, but it has a special role in our algorithms. We can differentiate initialization by using the **move** command and substitution variables rather than the **let** command. I try to initialize all my variables in my “start_program” procedure, in alphabetical order. Here are some approaches.

`#define initialize get`

#define to-zero from initzero(0)

#define to-null from initnull(0)

#define initialize-# move 0 to #

#define initialize-$ move '' to $

`begin-procedure create_arrays ! this can be in an include file`

create-array name=initzero size=1

field=zero0:integer=0

field=zero1:integer=0

field=zero2:integer=0

field=zero3:integer=0

field=zero4:integer=0

field=zero5:integer=0

field=zero6:integer=0

field=zero7:integer=0

field=zero8:integer=0

field=zero9:integer=0

`create-array name=initnull size=1`

field=null0:char=''

field=null1:char=''

field=null2:char=''

field=null3:char=''

field=null4:char=''

field=null5:char=''

field=null6:char=''

field=null7:char=''

field=null8:char=''

field=null9:char=''

end-procedure create_arrays

`begin-setup`

declare-variable

date $third_millenium

end-declare

end-setup

`begin-program`

{initialize} #a #b #c #d #e {to-zero}

{initialize} $a $b $c $d $e {to-null}

`move '01-JAN-2001' to $third_millenium date`

`{initialize-$}y ! no space between curley bracket and variable`

{initialize-#}z

end-program

We don’t have to include the # and $ symbols in the substitution variables, but we need one for numbers and one for strings. I thought the easiest way to name them was to use the symbols, and if I was using the symbols, I didn’t need to use the symbols again on the variables.

### Incrementing Variables

Adding one to a number is such a common and special operation that C gave us an operator that did nothing but that; x++ or ++x adds one to the x variable. Then, people named a language after that operator; C++, pronounced “cee plus plus.”

We add one to variables to count business objects (e.g. number of employees, number of customers) and to control our program flow (e.g. number of loop iterations). This is conceptually different from an operation like “let #y = #x + #a” where #a just happens to be equal to 1. It’s even different from an operation like “let #y = #x + 1” where #y is intended to be a value slightly greater than #x.

Here are some ways we can call attention to the fact that we’re not just doing addition, we are counting.

`#define count-# add 1 to`

#define next-# add 1 to

`{initialize-#}i`

while #i < #number_of_i

if emp.deptid(#i) = ‘1234’

{count-#}dept1234_employees

end-if

{next-#}i

end-while

Note that the substitution for {count-#} is the same code as for {next-#}, but count and next mean something different to the reader.

### Summing

I don’t like to use the **add**, **subtract**, **multiply**, or **divide** commands when they make me a liar, no matter how briefly. Consider these cases.

`move #foreign_revenue to #global_revenue`

`add #domestic_revenue to #global_revenue`

`subtract #expenses from #revenue`

`move #revenue to #profits`

At the end of the first command we have a value in #global_revenue that isn’t global revenue. If we put a **print** statement or a subroutine call between 1 and 2, we could use #global_revenue prematurely. If we perform the math and then the **move**, as with 3 and 4, we have the same problem. We can avoid this issue with the **let** command.

`let #global_revenue = #foreign_revenue + #domestic_revenue`

let #profits = #revenue - #expenses

You may disagree, and leave a comment if you do, but I feel these cases are different from the one below.

`{initialize-#}i`

{loop-with-#}i

get #amount from array(#i) amount

add #amount to #total

{next-#}i

{end-loop}

True, #total is not the total of the array until the last addition. However, it is the total of the amounts so far at every point. Also, loops suggest that any variables within a loop may have interim values. Finally, it’s not possible to unroll every loop into a single **let** command, especially those with an unpredictable number of iterations. On the other hand, the previous examples are easy to clarify with **let** commands.

### Subtract, Multiply, and Divide

I’ve done most of my “subtexting” with **move** and **add**. In my work experience, I haven’t had much opportunity to use **subtract**, **multiply**, and **divide** without feeling like a liar (see above).

I decremented loop counters in assembly language in order to use the “compare to zero” opcodes, but there’s no need to do that in a higher level language. I decremented an array index in my binary/linear search algorithm, but I only wrote that routine once.

I don’t want to “multiply #pay_rate times #hours” because the #hours variable shouldn’t contain gross pay, even for one line of the program. I haven’t had any assignments to calculate factorials or loan balances:

`move 1 to #factorial`

move 0 to #i

while #i <= #number

multiply #i times #factorial

add 1 to #i

end-while

`move 0 to #y`

while #y < #num_years

multiply 1.05 times #principal

add 1 to #y

end-while

The **divide** command has built-in “divide by zero” error handling, but I haven’t found a time to use it without “lying.” Has anyone else?

I disagree.

Thus I leave a comment.

But seriously… your example of looping to calculate a total is OK if there’s no way to exit the loop prematurely (just as calculating global_revenue is safe as long as no bozo sticks a line of code in the middle). But what if you leave the loop early due to an ON ERROR statement?

The real solution is to have a temporary variable (e.g. accumulate_total) in the loop that is discarded after the calculation.

I freely admit that I’m frequently too lazy to follow my own advice.

- Bob