Using VAR in a Parameter List

Product Version(s): 3.x
Operating System:   MS-DOS
Flags: ENDUSER | TAR52916
Last Modified: 24-MAR-1988    ArticleIdent: Q11494

Problem:
   In the following code (an excerpt from a larger program) the
parameter list contains a variable "Table". All other procedures in
the program that use Table use the parameter "VAR TABLE:TableArray",
but in this example, the PrintTable procedure declares it
"TABLE:TableArray".
   The program hangs because of this error. If you replace the
parameter with "VAR TABLE:TableArray" the program works correctly. We
think that the compiler should issue an error message in this
instance.

Response:
   The behavior of the Microsoft Pascal compiler is correct. In the
program you used, the procedure PrintTable contains a parameter list.
One of the parameters passed to PrintTable is "TABLE: TableArray;" and
your claim is that the program did not use the parameter "VAR
TABLE:TableArray".
   In Pascal, you can pass parameters to procedures by reference
(using VAR, or VARS between Modules or Units) or by value (by
default). If you use "TABLE:TableArray", you pass the parameter by
value, while "VAR TABLE:TableArray" passes it by reference. Both
methods are valid. Sometimes you may want to pass an array to a
procedure by value, and that is correct Pascal usage. In your program,
using the array in such a way hangs your program. But since both
instances (passing arrays by reference and passing them by value) are
correct Pascal usage, this is not an error on the part of the compiler
but rather a logic error that the user is responsible for. The
following is a short code excerpt:

{---------------------------------------------------------------------------}
{Search table for word if found increment count else call InsertWord.       }
{---------------------------------------------------------------------------}

PROCEDURE SEARCHTABLE (VAR TABLE: TableArray;        {<--Used correctly}
                   VAR TABLESIZE: integer;
                            WORD: String ;
         VAR FIRST, LAST, MIDDLE: integer);

var
     FOUND: boolean; {Check to see if word is found}

begin {SearchTable}
FIRST:= 1;
LAST:= TableSize;
FOUND:= false;
while (Last >= First) and (not Found) do
     begin {while}
     MIDDLE:= (First + Last) div 2;
     if Word < Table [Middle].Word then
             LAST:= Middle - 1
     else
     if Word > Table [Middle].Word then
             FIRST:= Middle + 1
     else
             begin {else}
             TABLE [MIDDLE].COUNT:= Table [Middle].Count + 1;
             FOUND:= true;
             end; {else}
     end; {while}
if (Last < First) and (not Found) then
     InsertWord (Table, TableSize, First, Word);
end; {SearchTable}

{---------------------------------------------------------------------------}
{Print the contents of Table to the screen.                                 }
{---------------------------------------------------------------------------}

PROCEDURE PRINTTABLE (TABLE: TableArray;             {<-- Correct usage but }
                   WordCount,                         {   incorrect logic  }
                  SENTCOUNT: integer);

var
     TABLET: integer; {Loop control variable in for loop}

begin {PrintTable}
writeln;
WRITELN ('CONTENTS OF: ',FileName);
WRITELN ('TOTAL SENTENCES: ',SentCount:1);
WRITELN ('TOTAL UNIQ WORDS: ',TableSize:1);
WRITELN ('TOTAL WORDS: ',WordCount:1);
writeln;
FOR TABLET:= 1 to TableSize do
     WRITELN (TABLE [TABLET].WORD,TABLE [TABLET].COUNT:1);
end; {PrintTable}
