Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2009-06

Writeable typed constants - what's the point?

26 messages · 11 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Hi,

Recently I learned that you can have writeable typed constants. That sounds rather like an oxymoron to my. Writeable constants make no sense, is that then simply a variable? What is the use of a writeable typed constant?

Below is two examples of how they can be used, and support for them are toggled with the compiler directive $J.

In both these cases I would think a variable would make a lot more sense. For the Singleton implementation, you simply need to specify a unit wide AppSingleton variable in the implementation section (so that it's not completely global or visible to other units.

Can anybody explain the point of writeable typed constants?

const
   foo: Integer = 12;
begin
   foo := 14;
end.

===============================

// Singleton implementation using typed constants
function gAppManager: TApplicationManager;
const
  {$IFDEF DELPHI}{$J+}{$ENDIF}
  AppSingleton: TApplicationManager = nil;
  {$IFDEF DELPHI}{$J-}{$ENDIF}
begin
  if not Assigned(AppSingleton) then
    AppSingleton := TApplicationManager.Create;
  Result := AppSingleton;
end;

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Vincent Snijders
to Graeme Geldenhuys
Graeme Geldenhuys wrote 7 lines
Hi, Recently I learned that you can have writeable typed constants. That sounds rather like an oxymoron to my. Writeable constants make no sense, is that then simply a variable? What is the use of a writeable typed constant?

Backwards compatibility with turbo pascal, which lacked initialized variables and writable constants were the alternative.

Vincent

Reply by email

Graeme Geldenhuys
to Vincent Snijders
Vincent Snijders wrote
Backwards compatibility with turbo pascal, which lacked initialized variables and writable constants were the alternative.

Thanks Vincent. The Kylix 3 help mentioned early versions of Delphi and Borland Pascal, which made me think that it must have been some limitation in the older compilers. Thanks for confirming this.

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Unknown author
to Vincent Snijders: Backwards compatibility with turbo pascal, which lacked initialized variables and…
Vincent Snijders wrote 10 lines
Graeme Geldenhuys schreef: > Hi, > > Recently I learned that you can have writeable typed constants. That > sounds rather like an oxymoron to my. Writeable constants make no sense, > is that then simply a variable? What is the use of a writeable typed > constant? Backwards compatibility with turbo pascal, which lacked initialized variables and writable constants were the alternative.

Is this likely to be dropped in future versions of FPC? I have taken advantage of this in functions where a static variable would be used in other languages like C.

In the following example, the typed constant Count is initialised only once when Test() is first called and thereafter retains its value between function calls.

procedure Test();
const
  Count : Cardinal = 1;
begin
   Writeln('The value of Count is now ', Count);
   Inc(Count);
end;
var
  i : LongInt;
begin
   for i := 1 to 10 do
      Test();
end.
will yield;

The value of Count is now 1
.
.
The value of Count is now 10

Although a writable constant makes no sense, it come in handy and is a cool feature to have. Perhaps a construct derived from this feature can be added to FPC?

Regards,
Nino

Reply by email

Graeme Geldenhuys
to Unknown author
Is this likely to be dropped in future versions of FPC?

No idea. But I have noticed that FPC (mode objfpc) defaults to allow writeable typed constants, whereas Delphi and Kylix doesn't. In the latter two compilers you have to enable is support with $J+ compiler directive.

I don't know (have not tested) what FPC does with mode delphi though. But seeing that this feature is just for backward compatibility, maybe it should be disallowed by default in mode objfpc as well?

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Graeme Geldenhuys
I don't know (have not tested) what FPC does with mode delphi though.

OK, just tested FPC modes objfpc and delphi. In both cases writeable typed constants are allow by default. This is not compatible with current Delphi compilers.

I still think this should be disable by default in both compiler modes - after all, it's just a backward compatibility feature to Turbo Pascal days.

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Jonas Maebe
to Vincent Snijders: Backwards compatibility with turbo pascal, which lacked initialized variables and…
Vincent Snijders wrote 10 lines
Graeme Geldenhuys schreef: > Hi, > Recently I learned that you can have writeable typed constants. That > sounds rather like an oxymoron to my. Writeable constants make no > sense, > is that then simply a variable? What is the use of a writeable typed > constant? Backwards compatibility with turbo pascal, which lacked initialized variables and writable constants were the alternative.

Writable constants behave completely different from initialised variables inside procedures/functions: writable constants are initialised once (at program startup) and keep their value across invocations, while initialised variables are re-initialised every time the procedure/function scope is entered.

I.e., local writable constants are basically global initialised variables that are only visible inside a local scope.

Jonas

Reply by email

Vincent Snijders
to Graeme Geldenhuys: OK, just tested FPC modes objfpc and delphi. In both cases writeable typed constants are…
Graeme Geldenhuys wrote 8 lines
> I don't know (have not tested) what FPC does with mode delphi though. OK, just tested FPC modes objfpc and delphi. In both cases writeable typed constants are allow by default. This is not compatible with current Delphi compilers. I still think this should be disable by default in both compiler modes - after all, it's just a backward compatibility feature to Turbo Pascal days.

I disagree. It would be backwards incompatible with existing objfpc programs. That decision should have been made 10 (?) years ago, when mode objfpc was introduced.

Vincent

Reply by email

Graeme Geldenhuys
to Vincent Snijders
Vincent Snijders wrote
I disagree. It would be backwards incompatible with existing objfpc programs. That decision should have been made 10 (?) years ago, when mode objfpc was introduced.

Not everything was done correctly 10 years ago (or first time round). There are many bug reports still being submitted to fix delphi compatibility issues in FPC. They are still being fixed today, so why must writeable typed constants be any different to those bug reports?

FPC often implements something that breaks existing code. If the code is being maintained, the developers can simply fix there code. I had to do that for fpGUI Toolkit, so why can't others. Lazarus code also has to be fixed constantly due to FPC changes in behaviour.

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Florian Klaempfl
to Graeme Geldenhuys
Show quoted text 6 lines
Vincent Snijders wrote: > I disagree. It would be backwards incompatible with existing objfpc > programs. That decision should have been made 10 (?) years ago, when > mode objfpc was introduced. Not everything was done correctly 10 years ago (or first time round).

Nevertheless, writable typed constants are simply an important part of Borland style Object Pascal.

Show quoted text 5 lines
There are many bug reports still being submitted to fix delphi compatibility issues in FPC. They are still being fixed today, so why must writeable typed constants be any different to those bug reports? FPC often implements something that breaks existing code.

Examples :)? Then I'll tell you what's the difference to writable typed constants.

Reply by email

Unknown author
to Vincent Snijders: I disagree. It would be backwards incompatible with existing objfpc programs. That…

It's intersting to note that as far back as Delphi 5,(oldest I have on my system), attempting to write to a typed constant causes a "left side cannot be assigned to" compiler error.

I guess as long as FPC compiler offers TP7 compatibility, this feature must be retained. Also, bear in mind that some developers might want to mix old style constructs with new ones, (TP7 object and Delphi classes), so restricting available feature to certain modes might not be the way to go.

Regards,
Nino

Reply by email

Marco van de Voort
to Florian Klaempfl: Nevertheless, writable typed constants are simply an important part of Borland style…

In our previous episode, Florian Klaempfl said:

Show quoted text 5 lines
> > Not everything was done correctly 10 years ago (or first time round). Nevertheless, writable typed constants are simply an important part of Borland style Object Pascal.

Is it, since D4 also supports var? I agree it is a sterile difference, but it provides an alternative to the use of CONST.

Reply by email

Graeme Geldenhuys
to Florian Klaempfl: Nevertheless, writable typed constants are simply an important part of Borland style…
Florian Klaempfl wrote
Nevertheless, writable typed constants are simply an important part of Borland style Object Pascal.

I'm not arguing that. Then maybe writeable typed constants should be disabled for compiler mode 's a Delphi compatibility issue after all.

Just this morning I got confirmation that code I wanted to implement in tiOPF did not compile under D7 and D2009. I had to introduce IFDEF Delphi and $J+ around the writeable constant. tiOPF and FPC used mode delphi throughout the framework.

> FPC often implements something that breaks existing code. Examples :)?

Please note that I am not saying I disagree with the changes. I know they were introduced for the better. What I am saying, is that changes do get introduced into FPC (for whatever reason) and does sometimes break existing code.

Example #1:
You cannot pass a property as var parameter anymore. Introduced in v2.2.0

Example #2:
Boolean type change in Xlib units. TBool(false) or TBool(true) type usage.

Example #3:
ComponentState change. I wasn't allowed to use the following code

  anymore:  Include(ComponentState, csDesigning);

I think there was a few more that affected fpGUI Toolkit project, but I think you get the idea. As long as code is being maintained, such changes are not the end of the world. :-) But my point is, they do happen!

Then I'll tell you what's the difference to writable typed constants.

OK, now tell me... :-)

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Martin Friebe
to Graeme Geldenhuys
Graeme Geldenhuys wrote 29 lines
>> FPC often implements something that breaks existing code. >> > Examples :)? > Please note that I am not saying I disagree with the changes. I know they were introduced for the better. What I am saying, is that changes do get introduced into FPC (for whatever reason) and does sometimes break existing code. Example #1: You cannot pass a property as var parameter anymore. Introduced in v2.2.0 Example #2: Boolean type change in Xlib units. TBool(false) or TBool(true) type usage. Example #3: ComponentState change. I wasn't allowed to use the following code anymore: Include(ComponentState, csDesigning); I think there was a few more that affected fpGUI Toolkit project, but I think you get the idea. As long as code is being maintained, such changes are not the end of the world. :-) But my point is, they do happen!

Afaik 1 & 3 are the same?

And if I understand the changes where mad, because this "feature" was broken before:
That is the syntax you mentioned lead to an unpredictable result, and the circumstances under which it did what you wanted could change outside your code and without the intend to make them change.

Or in other words: This only worked if a property directly read a variable, but not if it was a function result => meaning you had 2 different types of properties. But only one was documented.

Best Regards
Martin

Reply by email

Graeme Geldenhuys
to Martin Friebe
Martin Friebe wrote
Afaik 1 & 3 are the same?

True.

And if I understand the changes where mad, because this "feature" was broken before:

To quote myself, even though I know one shouldn't. ;-)

"I know they were introduced for the better."

I was not arguing the point that those changes should not have been made. I was simply stating that other projects code was broken due to behaviour changes made in FPC. This was my counter argument to Vincent's reply that it would break existing code.

If external projects are still being maintained, they should keep up with the latest FPC. I do it with fpGUI, Martin does it with MSEide+MSEgui and Lazarus does it, etc...

So I don't see a problem if FPC made $J- the default behaviour in FPC mode delphi. At least FPC is then Delphi compatible - which is one of FPC's goals I believe. And as Nino pointed out, even the old Delphi 5 doesn't allow writeable typed constants by default.

What should be the default behaviour in mode objfpc? Well that I am not sure about.

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Martin Friebe
to Graeme Geldenhuys
Graeme Geldenhuys wrote 15 lines
Martin Friebe wrote: > And if I understand the changes where mad, because this "feature" was > broken before: > To quote myself, even though I know one shouldn't. ;-) "I know they were introduced for the better." I was not arguing the point that those changes should not have been made. I was simply stating that other projects code was broken due to behaviour changes made in FPC. This was my counter argument to Vincent's reply that it would break existing code.

I know you said that, but I tried to highlight something that imho is missing in this statement.

The change with "properties as var param" only broke existing code, if this existing code was already broken. The compiler just compiled the broken code before. Nor the compiler rejects the broken code.

To explain:
- A property has always been defined as beeing equal in treatment to the result of a function. This is the purpose of a property. If you do not want to be able to replace the property getter/setter by a function/procedure => you can just publish the variable.
- a function result was never allowed as "var param" (just not possible) => In other words being allowed to do the impossible (defeating the purpose of a property), means being allowed to compile broken code => which must be fixed, even if it breaks projects that relied on it. But those projects should anyway never have compiled.

procedure a;
const
 i: integer = 1;

is a documented, working feature, there is nothing broken about it.

----
Anyway here another view on the topic:

1) I think the feature in itself is useful and should exist
2) the current syntax of the feature is not very self-explaining. Reading code with this feature is misleading

If at all something should be done about, imho it was introducing an alternative, more readable syntax, but keeping the old (because it is a documented feature / maybe add a compiler hint for the old syntax)

People who care about the read ability of their code could the write a more intuitive form.

Maybe

procedure a;
var
  x: integer = 1; static;

or if there is, or is planned, whatever syntax there is or will be for class members of this kind

Best Regards
Martin

Reply by email

Paul Nicholls
to Graeme Geldenhuys: Thanks Vincent. The Kylix 3 help mentioned early versions of Delphi and Borland Pascal,…

2009/6/18 Graeme Geldenhuys

Show quoted text 13 lines
Vincent Snijders wrote: > > Backwards compatibility with turbo pascal, which lacked initialized > variables and writable constants were the alternative. Thanks Vincent. The Kylix 3 help mentioned early versions of Delphi and Borland Pascal, which made me think that it must have been some limitation in the older compilers. Thanks for confirming this. Regards, - Graeme -

I also find writable constants hand for things like this where I can define the 'variable' + values too so I don't have to set the values at run time:

Const
{..............................................................................}

    cNote_Unknown = -1;
    cNote_C       = 0;
    cNote_Cs      = 1;  cNote_Db = 1;
    cNote_D       = 2;
    cNote_Ds      = 3;  cNote_Eb = 3;
    cNote_E       = 4;
    cNote_F       = 5;
    cNote_Fs      = 6;  cNote_Gb = 6;
    cNote_G       = 7;
    cNote_Gs      = 8;  cNote_Ab = 8;
    cNote_A       = 9;
    cNote_As      = 10; cNote_Bb = 10;
    cNote_B       = 11;
    cNotes : Array[0..11,0..8] Of Single =
    (
        //Octave

//Note 0 1 2
3 4 5 6 7 8
{C} (16.3515978312874, 32.7031956625748, 65.4063913251497, 130.812782650299, 261.625565300599, 523.251130601197, 1046.50226120239, 2093.00452240479, 4186.00904480958),
{C#/Db} (17.3239144360545, 34.647828872109 , 69.295657744218 , 138.591315488436, 277.182630976872, 554.365261953744, 1108.73052390749, 2217.46104781498, 4434.92209562995),
{D} (18.354047994838 , 36.7080959896759, 73.4161919793519, 146.832383958704, 293.664767917408, 587.329535834815, 1174.65907166963, 2349.31814333926, 4698.63628667852),
{D#/Eb} (19.4454364826301, 38.8908729652601, 77.7817459305202, 155.56349186104 , 311.126983722081, 622.253967444162, 1244.50793488832, 2489.01586977665, 4978.03173955329),
{E} (20.6017223070544, 41.2034446141088, 82.4068892282175, 164.813778456435, 329.62755691287 , 659.25511382574 , 1318.51022765148, 2637.02045530296, 5274.04091060592),
{F} (21.8267644645628, 43.6535289291255, 87.307057858251 , 174.614115716502, 349.228231433004, 698.456462866008, 1396.91292573202, 2793.82585146403, 5587.65170292806),
{F#/Gb} (23.1246514194772, 46.2493028389543, 92.4986056779086, 184.997211355817, 369.994422711634, 739.988845423269, 1479.97769084654, 2959.95538169308, 5919.91076338615),
{G} (24.4997147488593, 48.9994294977187, 97.9988589954373, 195.997717990875, 391.995435981749, 783.990871963499, 1567.981743927 , 3135.96348785399, 6271.92697570799),
{G#/Ab} (25.9565435987466, 51.9130871974931, 103.826174394986, 207.652348789973, 415.304697579945, 830.60939515989 , 1661.21879031978, 3322.43758063956, 6644.87516127912),
{A} (27.5 , 55 , 110 , 220 , 440 , 880 , 1760 , 3520 , 7040 ),
{A#/Bb} (29.1352350948806, 58.2704701897613, 116.540940379522, 233.081880759045, 466.16376151809 , 932.32752303618 , 1864.65504607236, 3729.31009214472, 7458.62018428944),
{B} (30.8677063285078, 61.7354126570155, 123.470825314031, 246.941650628062, 493.883301256124, 987.766602512248, 1975.5332050245 , 3951.06641004899, 7902.13282009799)

    );

{..............................................................................}

Notice the cNotes array - it is already filled with values for me to use at runtime :)

cheers,
Paul

Reply by email

Jürgen Hestermann
to Paul Nicholls
Paul Nicholls schrieb: I also find writable constants hand for things like this where I can define the 'variable' + values too so I don't have to set the values at run time:

But can't you do the same with a variable declaration? If you want to change the value at runtime it's definitely not a constant anymore.

Beeing able to change a typed constant was added by Borland as a "quick hack" (because constants were put into the global data segement even in function declarations) but actually its semantic is wrong. If you can change it, it has to be a variable declaration and you should not be able to change a constant.

Jürgen Hestermann

Reply by email

Martin Friebe
to Jürgen Hestermann
Jürgen Hestermann wrote 9 lines
> Paul Nicholls schrieb: > I also find writable constants hand for things like this where I can > define the 'variable' + values too so I don't have to set the values > at run time: But can't you do the same with a variable declaration? If you want to change the value at runtime it's definitely not a constant anymore.

Not always

Show quoted text 6 lines
Beeing able to change a typed constant was added by Borland as a "quick hack" (because constants were put into the global data segement even in function declarations) but actually its semantic is wrong. If you can change it, it has to be a variable declaration and you should not be able to change a constant.
there is an important difference between
const a: word = 1;
const a = word(1); // never writeable
var a: word = 1;

The1 1st and 3rd are (afaik) the same, if used top level, that is in the global context of interface, or implementation
.

But if
procedure Foo;
  const a: word = 1;
  var a: word = 1;
begin
end;

Then they are 2 difference things.

The "var" version, acts as if your first statement in the procedure was "a:= 1;". It initializes the variable each time you enter the function. If you enter the function recursively, then each level, has it's own a, not touching the value of the callers a

The const version act like a global variable. It is set to 1 once at some time before the 1st call to Foo. It will not be initialized again. If Foo chages it, it will keep the changed value, even between calls to Foo. If Foo enters recursively, it act like a global var, there is only one a, shared by all calls to Foo.
If Foo is a Method on an object, then it is shared between all instances of the object.
The only difference to a global var is, that no one outside Foo can see or access it.

And you can't do that with an initialized var. And there are plenty of use-cases for it.

Martin

Reply by email

Graeme Geldenhuys
to Martin Friebe
Martin Friebe wrote
The const version act like a global variable. It is set to 1 once at some time before the 1st call to Foo. It will not be initialized again. If Foo chages it, it will keep the changed value, even between calls to

Then this is a language issue. 'const' is clearly not the correct type declaration for that variable. As suggested suggested earlier, it would make more sense to maybe implement something like shown below - or whatever language construct the developers can come up with.

var
  a: word = 1; static;

'const' or constant is simply not a very accurate description of the usage of that "writeable" variable/constant. It goes against the "easy readability design" of the Object Pascal language, and is very unclear as to the meaning of that typed constant.

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Jürgen Hestermann
to Martin Friebe: Not always there is an important difference between const a: word = 1; const a = word(1);…
The "var" version, acts as if your first statement in the procedure was "a:= 1;". It initializes the variable each time you enter the function. If you enter the function recursively, then each level, has it's own a, not touching the value of the callers a

I also used Borlands "const-hack" a lot. But now I changed my behaviour and use VAR declarations directly before the function declaration (one level higher, outside the function context). That serves the same purpose.

Jürgen Hestermann.

Reply by email

David W Noon
to Jürgen Hestermann
Jürgen Hestermann wrote 8 lines
> The "var" version, acts as if your first statement in the procedure was > "a:= 1;". It initializes the variable each time you enter the function. > If you enter the function recursively, then each level, has it's own a, > not touching the value of the callers a I also used Borlands "const-hack" a lot. But now I changed my behaviour and use VAR declarations directly before the function declaration (one level higher, outside the function context). That serves the same purpose.

The writeable const hack is slightly different in that the scope of the inconstant constant is local to the function, whereas moving it to a var at global scope makes it visible to all functions within the unit.

This issue has been a criticism of the Pascal language dating back to the days of Jensen and Wirth. In ALGOL 60, variables with static duration were declared as "own", which made no sense in English terms; worse still, ALGOL 60 had no initializers at all, so these variables could not be initialized at program load time. In contrast, PL/I used the attribute STATIC, which described the semantics concisely, and permitted an INIT() option to set an initial value. [In those days, both FORTRAN and COBOL used static duration with no option available to alter it. Yuck!]

I think it is more expressive to make the semantics clear by declaring an inconstant constant as a variable -- because that's what it is -- with a duration modifier to show that it has static duration. I suppose that for symmetry there should be an antonym, automatic, which is accepted by the compiler but produces the current, default semantics.

Regards, Dave [RLU #314465] ======================================================================= (David W Noon) =======================================================================

Reply by email

Richard Ward
David Noon wrote
I think it is more expressive to make the semantics clear by declaring an inconstant constant as a variable -- because that's what it is --

This semantic issue is very confusing for beginners including people who are migrating from a non Borland environment. In my opinion also, the semantics should be changed to reflect the actual nature of the construct and behavior. This would have saved me considerable time when I was trying to figure out why it that particular construct was there in the first place. Again, imo, it would be better if someone who was migrating from Delphi, found that their FPC program didn't compile could look in the manual and make the global changes rather than have someone new introducing bugs into their programs because they were confused on the concept. I also wager it would be at least a wash for the various mailing list moderators fielding questions from Delphi migraters vs. new programmers. At least the Delphi migrators should (hopefully) have an understanding of the concept already. And if they really didn't understand the concept, this would flush out the misconception. - ROW

Reply by email

Jürgen Hestermann
to Richard Ward
Richard Ward schrieb: In my opinion also, the semantics should be changed to reflect the actual nature of the construct and behavior.

Agree.

Show quoted text 5 lines
Again, imo, it would be better if someone who was migrating from Delphi, found that their FPC program didn't compile could look in the manual and make the global changes rather than have someone new introducing bugs into their programs because they were confused on the concept.

I fully agree. It is a much better approach to let a programmer change his own program when porting things than having some kind of compatibility mode which is then used for new programs too so that you never get rid of awkward coding hacks.

Show quoted text 6 lines
I also wager it would be at least a wash for the various mailing list moderators fielding questions from Delphi migraters vs. new programmers. At least the Delphi migrators should (hopefully) have an understanding of the concept already. And if they really didn't understand the concept, this would flush out the misconception. - ROW

Agree again.

Jürgen Hestermann.

Reply by email

David W Noon
to Jürgen Hestermann
Jürgen Hestermann wrote 6 lines
> Richard Ward schrieb: > In my opinion also, the > semantics should be changed to reflect the actual nature of the > construct and behavior. Agree.

I think Richard Ward actually meant the syntax, not the semantics.

The semantics of static duration are fixed and need to be so. The current syntax of the "inconstant constant" is nonsensical, really. It smacks of an almighty kludge.

Regards, Dave [RLU #314465] ======================================================================= (David W Noon) =======================================================================

Reply by email