From: thompson@atlas.socsci.umn.edu (T. Scott Thompson)
Subject: Undocumented Feature?  Was: behavior of typed constants in subroutines
Reply-To: thompson@atlas.socsci.umn.edu
Organization: Economics Department, University of Minnesota
Date: Tue, 13 Oct 1992 15:24:56 GMT

jboor@mote.cs.umb.edu (Joan Boorstein) writes:

>In article <Bw0o2C.9qn@news.cso.uiuc.edu> amead@s.psych.uiuc.edu (Alan Mead) writes:
>>Wow, I've never had a formal Pascal education, but I thought I knew
>>all the important things.  I always thought that if you wanted a
>>variable's value to persist from subroutine call to subroutine call
>>(like a C static) that you had to declare it global...  I never knew
>>that a typed constant would do the same thing:
>>
>>program test;
>>
>>  procedure fgj;
>>    const
>>      x : longint = 1;
>>    begin
>>      x := x + 1;
>>      write( x:10 );
>>    end;
>>
>>begin
>>  fgj;
>>  fgj;
>>  fgj;
>>  fgj;
>>end.
>>
>>Is there any way I can get burned?  Is this slower or faster than
>>declareing the structure globally?  I really prefer keeping the scope
>>to the routine that needs to use it.

>I'd first like to ask if you tried compiling your code.  I'd doubt it
>would -- it didn't for me, using a VAX-11 Pascal compiler -- as I expected
>it wouldn't, but I wanted to check.  If you had done so, it would have
>probably answered your question.

His program compiles and runs just fine under Turbo Pascal.  He should
have made it clear that this is what he is using since he is using TP
extensions to "standard" Pascal.

>First, there is no output declared in the program header, so you can't
>use write -- that is a minor matter and eaily fixed.

Not a problem in Turbo Pascal.

>The real problem I see here is that you declare x to be a constant, but
>then change its value.  The Pascal compiler will complain when you try
>to change the value of identifier which is declared to be a consant.  You
>can't use a constant identifier on the left-hand-side of an assignment
>statement.  If you want to change an identifier's value, it must be declared 
>as a variable, giving it a appropriate type.  I am also not familiar with a
>compiler allowing you to declare the type of the constant -- didn't think
>this was standard (but I don't have the appropriate document to check here).

I do not know if the "const" keyword is standard, but it is very
common.  Unfortunately, in TP it is used to implement two quite
different features:

const x = 1;

const longint : x = 1;

The first is called a "constant" in the TP documentation, and works
just like the "const" declaration in most other Pascals.  The second
is called a "typed constant" in the TP documentation, and is really a
preinitialized variable, not a constant.  It is unfortunate that
Borland used the "const" keyword, and such an unusual syntax, to
implement preinitialized variables.

The point of the original post is that evidently TP does not
reinitialize the typed constants declared local to a procedure, and
stores them in static memory.  So they work just like a variable with
global scope, except that you can only reference them from inside the
procedure.

Followup questions:

I find that the variable x is treated as if it is a global static in
the following program:

program test;
  procedure fgj;
    const x : integer = 1;
    begin
    writeln(x);
    if x < 5 then
       begin
       x := x + 1;
       fgj;
       end;
    writeln(x);
    end;
begin
fgj;
end.

The output sequence is: 1 2 3 4 5 5 5 5 5 5

This shows that (a) the value of x is not reinitialized on each entry
to fgj; (b) even though x is _local_ to fgj, and _not_ a VAR
parameter, a fresh copy is not made upon entrance to fgj.  Thus x does
not behave like other locally decalared variables in recursive calls.

This seems like an inconsistency (bug?) in TP.  According to the TP
5.0 User's Guide, p. 143, (I don't have my 6.0 manuals at work)

   "Each time a function is called recursively, it creates a new set
    of local variables and pass-by-value (non-var) parameters."

Evidently locally declared typed constants are an exception since
local copies are not created on entry.

Is this behavior documented?  Are programs that rely on the apparently
static nature of locally declared typed constants likely to break in
future releases of TP?  Does it work even in procedures that are
defined within overlay units?  (The TP 5.0 manual says that typed
constants are stored in the data segment, so I will guess that
overlays don't matter, at least for the present.)

IMHO the best way (in TP) to implement "static" variables is to make
them global.  If you want to hide them from code outside your
procedure, then put them in the implementation section of a unit
defining the procedure.
--
T. Scott Thompson              email:  thompson@atlas.socsci.umn.edu
Department of Economics        phone:  (612) 625-0119
University of Minnesota        fax:    (612) 624-0209