[fpc-devel] Limitations of static "ranged" integer types andsucc/pred, and dynamic solution.

Vinzent Höfler JeLlyFish.software at gmx.net
Fri Dec 23 23:58:34 CET 2011

On Fri, 23 Dec 2011 03:39:03 +0100, Skybuck Flying
<skybuck2000 at hotmail.com> wrote:

> The reason for the proposal to add a dynamic/runtime version of  
> Low/High/Succ/Pred is pretty simply:
> Currently there simply is no dynamic/runtime version of it.

So what? I don't think that's necessary.

> Thus any code which is written using low/high/succ/pred is static in  
> nature, when the code needs to be changed to dynamic it's likely that  
> this will cause problems.

No, it won't.

> The problems are a bit vague, perhaps even hard to spot, correct and  
> understand, I am not going to examine these problems in detail right  
> now, but these problems probably exist.

Probably? If you want a whole new feature in a language which _by_ _design_
is based on static types, you should find a use case where no other  
exists. (For certain values of "exist", of course.)

> All that is needed to fix these problems is a dynamic version of these  
> methods.

Yeah, and all is needed to write correct software is the single processor
instruction: DWIM (Do What I Mean). Unfortunately nobody has implemented  

> I'll shall try to give one example of a potential problem:
> Situation 1:
> type
>   Tvalue = 0..5000;
> var
>   vIndex : TValue;
>   vA : TValue;
>   vB : TValue;
> for Index := Low(TValue) to High(TValue) do
> begin
>    if vA = High(TValue) then
>    begin
>        vA := Low(TValue);
>    end else
>    begin
>        vA := Succ(vA);
>    end;
> end;
> ^ This is a real world example and will probably compile just fine or  
> perhaps with a few correction.
> Now suppose the Tvalue can no longer be static

Now, you should explain why this can't be the case. Not simply state that
it is so.

Actually, I never needed a dynamic range type. But that, of course, doesn't
say they aren't useful per se, but to convince someone as ignorant as me  
should at least tell a use case where one would be really needed why you
can't get away with local type declarations then.

> and must be changed to dynamic, a choice could be made to turn this into  
> a smallint like so:
> TValue = smallint
> Suddenly this changes the range of low, high, succ, pred.

Yes, and everything still works, because the range is still static.

> At runtime the real range is set, for example to 32000.

Why? If the range changes during runtime, you probably don't even need a
range in the first place.

> This breaks all the code, the wrap backs will be wrong, the vA will go  
> out of range and will go to 32768 and perhaps even wrap back to negative.

Yes, but that's because you are not using the range of the type, but  
some arbitrary sub-range the compiler doesn't even know about.

> Thus by simply changing the "ranged" static Tvalue to a more "open  
> range" static integer type a whole can of worms/problems is opened.

Yes. So my question would be, why are you so keen on opening it? ;) What
shall happen to all those dependent variables that are declared with that
type? What happens to arrays using this type as index? Not to mention that
it seems a bad idea to let the range change dynamically. After all, obeying
the range is some property which is checked at run-time especially for the
reason that sometimes people like me are stupid enough to violate it.

While I'm at it, what about an adapting range type? For example, all ranges
start with an empty range (let's say "1 .. 0") and each time you assign a
value to a variable of that type, it will adapt to the new range, assuming
that me - as the programmer - was completely free of errors when doing it.
Of course, all other variables declared adapt the same way:

    Something = <>; // "<>" seems like a nice symbol for "anything"

    A : Something;
    B : array[Something] of Integer; // Initially a zero-size array.

WriteLn (Low (A), " .. ", High (A), "/", Length (B)); // prints "1 .. 0/0".
A := 1;
WriteLn (Low (A), " .. ", High (A), "/", Length (B)); // prints "1 .. 1/1"  
A := -50000;
WriteLn (Low (A), " .. ", High (A)); // prints "-50000 .. 1/50002" now.

Nice idea, eh? NOT.

> These problems could be more easily solved if Low/High/Succ/Pred was  
> more dynamic in nature and could adept to the runtime change.

I don't see problems here. If I have a type "TrafficLight" that goes from
"Red" via "Yellow" to "Green", I don't see any reason why I should be able
to suddenly add a "Blue" value to it at run-time.

Pascal is a statically typed language. And statically types usually means
just that: Statically. This includes some properties of a type like the
minimum and maximum value it can take.


More information about the fpc-devel mailing list