June 20, 2005
SQR Variable Oddities
I ran across some strange code in a program the other
day. It was essentially the following:
display 'The word is: '
Obviously this should display "The word is: hello" on two lines,
right? Well, it actually displays (using SQR for PeopleSoft 8.17)
only "0.000000e+000". Notice the lack of "LET" on the second
line of the code. This line becomes an extension of the DISPLAY
statement, with weird results. I thought it was trying to
turn "$x='hello'" into a boolean value, but even if $x really
is equal to "hello", the same thing happens. And I don't know what
happened to "The word is".
LET, on the other hand, really will try to evaluate true/false
let $x = 'hello'
let #result = $x='hello'
show #result ! 1.000000
In this case, 1 means "true". SHOW will also
give us this boolean value:
show $x='hello' ! 1.000000
No surprise there. But now watch what happens
if we use MOVE in a strange way...
move 'hi' to $x='hello'
show $x='hello' ! hi
let $x='hello' = 'something else'
show $x='hello' ! hi
MOVEing a value to $x='hello' somehow changes
it from a boolean expression into a variable! But the variable
can't be assigned a value using LET. It just keeps its value
and there is no error message.
So if $x='hello' is a (sort of) legal variable name, are there
any real restrictions on what we can name our variables? It
depends. MOVE lets us use just about any combination of
characters we want. LET, on the other hand, tries to determine
if it's a variable, expression, function call or array reference.
For example, the following is legal:
move 123 to #123-456,$$$789...(isn't_this_is_a_strange_variable?)
LET, however, will not be able to figure out that
that is a variable.
So does that mean we should use MOVE instead
of LET? No. There seem to be two families of statements in SQR. The first group
is COBOL-like: MOVE, DISPLAY, ADD, SUBTRACT, MULTIPLY, DIVIDE.
The second group is BASIC-like: LET, SHOW and the various functions.
These are far more flexible than the MOVE/DISPLAY family. For
example, while LET can calculate, call functions, concatenate
strings and format results, MOVE can only move data from one simple
source, with an optional formatting step. DISPLAY is similar.
It outputs one thing with optional formatting. SHOW allows you
to output any number of items and format them along the way.
So even though MOVE allows us to construct weird variable names,
don't do it. SQR may have trouble interpreting them. (The
will too, although I'm working on it!) I strongly recommend
that you restrict your variable names to containing only letters,
digits, underscores (_) and dots (.).
Speaking of which...Release 1.5 of the debugger, available
starting today, will attempt to identify certain coding practices
that could indicate logic errors in your code. It finds
(in most cases) the following:
- Variables occurring only once, which could indicate
variable name misspellings.
- Local variables having the same name as predefined global variables
(such as #END-FILE) without the leading underscore, which will not
work correctly if they were intended to be the predefined variables.
- Global variables containing a leading underscore in global
procedures (e.g., #_X found in a global procedure), which could have
been copied out of a local procedure and will not work if assumed to
be the same as a normal global (#X).
- Local variables that are passed as parameters to the procedure and
are modified within the procedure, but are not defined with the leading
- #DEFINE or ASK found within a run-time control structure (IF, WHILE,
EVALUATE, BEGIN-SELECT), which might indicate a misunderstanding of how
these directives work and can lead to bugs.
- One-character literals occurring in both upper- and lower-case
forms ('Y' and 'y').
Each of these situations could be OK within the context of a particular
program, but they can very easily cause bugs. In my experience,
these are some of the more common
causes of bugs, while being some of the toughest ones to find. Run
the debugger on some of your code and you might be surprised.
Until next time...