Recent

Author Topic: Initialising a record  (Read 8745 times)

mtanner

  • Sr. Member
  • ****
  • Posts: 287
Initialising a record
« on: April 25, 2021, 10:47:08 am »
This is not a very important question, just one of those niggling coding questions, and one which would frequently save me a line of code if I could do it.

I suspect the answer might teach me something interesting about Lazarus/FPC..

I define a record, say

TStuff=record
   A:double;   { detailed fields not important }
   B:integer;
end;

and a const:

const StuffZero:TStuff=(A:Nan;B:zero);

and I can then code

var MyStuff:TStuff;
MyStuff:=StuffZero;

but I cannot code:

var MyStuff:TStuff=StuffZero;


It puzzles me why this is so when I can code

var X:double=0;
and similarly for user-defined scalar variables.

wp

  • Hero Member
  • *****
  • Posts: 13350
Re: Initialising a record
« Reply #1 on: April 25, 2021, 11:35:41 am »
This is because of the peculiar construct (inherited from Turbo Pascal) that a typed "const" with initialization is not a constant, but an initialized variable. Therefore, it is not known whether StuffZero has not been changed along the way until it is assigned to MyStuff.

Likewise, the following simpler code does not work either:
Code: Pascal  [Select][+][-]
  1. // This does not work because "zero" is not necessarily constant
  2. const
  3.   zero: Integer = 0;
  4. var
  5.   x: Integer = zero;
  6.  
  7. // But this works because zero cannot be changed
  8. const
  9.   zero = 0;
  10. var
  11.   x: Integer = zero;

mtanner

  • Sr. Member
  • ****
  • Posts: 287
Re: Initialising a record
« Reply #2 on: April 25, 2021, 12:17:25 pm »
Thanks, useful to understand.

Just out of curiosity, does  C/C++ have similar initialisation constructs?

korba812

  • Sr. Member
  • ****
  • Posts: 482
Re: Initialising a record
« Reply #3 on: April 25, 2021, 12:37:06 pm »
There is a workaround for this problem by using macros or "management operators":
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$MACRO ON}
  4. {$modeswitch ADVANCEDRECORDS}
  5.  
  6. uses
  7.   Math;
  8.  
  9. type
  10.  
  11.   { TStuff }
  12.  
  13.   TStuff=record
  14.     A:double;   { detailed fields not important }
  15.     B:integer;
  16.     class operator Initialize(var ARec: TStuff);
  17.   end;
  18.  
  19. const
  20.   Zero = 0;
  21.  
  22. {$define StuffZero:=(A: Nan; B: Zero)}
  23.  
  24. var
  25.   MyStuff: TStuff = (A: Nan; B: Zero);
  26.   MyStuff2: TStuff = StuffZero;
  27.   MyStuff3: TStuff;
  28.  
  29. { TStuff }
  30.  
  31. class operator TStuff.Initialize(var ARec: TStuff);
  32. begin
  33.   ARec.A := Nan;
  34.   ARec.B := Zero;
  35. end;
  36.  
  37. begin
  38.   WriteLn(MyStuff.A);
  39.   WriteLn(MyStuff2.A);
  40.   WriteLn(MyStuff3.A);
  41. end.

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: Initialising a record
« Reply #4 on: April 25, 2021, 03:08:09 pm »
You can also call Default() to initialize records.
Aside: NaN should be detectable, but not assignable.
In general, indeed, you can use the management operator as described above.

Technically, though, initializing to NaN at compile time should throw an error. Same with infinity too.

Regarding other languages: I am not aware of C++ (certainly not C) being able to do that at compiler level. That would be library level. There are no intrinsics for this scenario in C style languages.

The gish is that both NaN and infinity can not be logically expressed as a constant. (And obviously, they are not!) NaN - 1 is undefined, Infinity + 1 is still infinity....
« Last Edit: April 25, 2021, 03:22:51 pm by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

jamie

  • Hero Member
  • *****
  • Posts: 7516
Re: Initialising a record
« Reply #5 on: April 25, 2021, 03:50:53 pm »
This is not a very important question, just one of those niggling coding questions, and one which would frequently save me a line of code if I could do it.

I suspect the answer might teach me something interesting about Lazarus/FPC..

I define a record, say

TStuff=record
   A:double;   { detailed fields not important }
   B:integer;
end;

and a const:

const StuffZero:TStuff=(A:Nan;B:zero);

and I can then code

var MyStuff:TStuff;
MyStuff:=StuffZero;

but I cannot code:

var MyStuff:TStuff=StuffZero;


It puzzles me why this is so when I can code

var X:double=0;
and similarly for user-defined scalar variables.

it's a compiler deficiency and all the blanket theories does not help in the cause.

Be glad you have what you got. I need to check Delphi but I wonder if it even supports doing this with the basic types?


The only true wisdom is knowing you know nothing

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: Initialising a record
« Reply #6 on: April 25, 2021, 04:02:04 pm »
it's a compiler deficiency
No it is not. It it pure logic.
At the most the issue at hand describes some deficiency in Boolean logic.. which happens to be the basis of modern computing....
« Last Edit: April 25, 2021, 04:04:33 pm by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

PascalDragon

  • Hero Member
  • *****
  • Posts: 6311
  • Compiler Developer
Re: Initialising a record
« Reply #7 on: April 25, 2021, 09:36:36 pm »
it's a compiler deficiency and all the blanket theories does not help in the cause.

Be glad you have what you got. I need to check Delphi but I wonder if it even supports doing this with the basic types?

The behavior is the same in Delphi and even TP.

jamie

  • Hero Member
  • *****
  • Posts: 7516
Re: Initialising a record
« Reply #8 on: April 25, 2021, 09:40:48 pm »
it's a compiler deficiency and all the blanket theories does not help in the cause.

Be glad you have what you got. I need to check Delphi but I wonder if it even supports doing this with the basic types?

The behavior is the same in Delphi and even TP.

I checked Delphi, unless there is a switch I don't have on, I can not initialize the variables in the VAR section with Delphi, Fpc can do that.

this is with 10.3, I can check 10.4 tomorrow..
The only true wisdom is knowing you know nothing

PascalDragon

  • Hero Member
  • *****
  • Posts: 6311
  • Compiler Developer
Re: Initialising a record
« Reply #9 on: April 25, 2021, 09:46:18 pm »
it's a compiler deficiency and all the blanket theories does not help in the cause.

Be glad you have what you got. I need to check Delphi but I wonder if it even supports doing this with the basic types?

The behavior is the same in Delphi and even TP.

I checked Delphi, unless there is a switch I don't have on, I can not initialize the variables in the VAR section with Delphi, Fpc can do that.

this is with 10.3, I can check 10.4 tomorrow..

I am talking about global variables and constants. No one here said anything about local variables.

For local variables FPC indeed allows initialization while Delphi does not, but FPC follows the same rules as for global variables which behave the same between FPC and Delphi.

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Initialising a record
« Reply #10 on: April 25, 2021, 11:08:38 pm »
it's a compiler deficiency
No it is not. It it pure logic.

Note that it happens (the compiler error) even if {$J-} (or {$WRITEABLECONST OFF} or -Sj-) is specified, which although "understandable" is not quite as logical :-\
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

mtanner

  • Sr. Member
  • ****
  • Posts: 287
Re: Initialising a record
« Reply #11 on: April 28, 2021, 11:27:45 am »
Thanks for all the info. Just a couple of comments.

Nan is a valid state for a double variable, and if it is detectable than I do not see why it should not be assignable. I have a fairly complicated set of routines for evaluating the performance (meaning a vector/record of several different measurements) of systems which are similar but with important differences, such that some measurements are not relevant for some system variants. So it is useful to set the vector of measurements to Nan at the start of each evaluation routine, so that a calling routine can detect that some particular measurement value has not been calculated (either because it is not relevant, in which case the calling routine has a bug by trying to use it, or because the evaluation routine has a bug in that it is not providing a result that it should do.

I am here using Nan to mean "undefined" rather than "numerically invalid".

I get the fact that compatibility with Delphi is important, but would it be sensible/possible to have an alternative to "const", say "constfix" to declare a record that really is constant, not just an initialised variable as in Delphi, and it could then be possible to write

constfix FixRec:TMyRec=(A:0;B:Nan,....
...
var LclRec:TMyRec=FixRec;


A related question is that I can write

var X:double=123;
var Y:double=123;
but not
var X,Y:double=123;

The last statement seems to me completely unambiguous, and would be usefully more concise.

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: Initialising a record
« Reply #12 on: April 28, 2021, 11:48:03 am »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

mtanner

  • Sr. Member
  • ****
  • Posts: 287
Re: Initialising a record
« Reply #13 on: April 28, 2021, 12:59:43 pm »
Thaddy, I will study the link you gave with interest.

Seems like particle physics, ask a question and the answer just leads to deeper questions!
« Last Edit: April 28, 2021, 01:17:49 pm by mtanner »

mtanner

  • Sr. Member
  • ****
  • Posts: 287
Re: Initialising a record
« Reply #14 on: April 28, 2021, 01:06:41 pm »
Perhaps the "correct" way for what I am trying to achieve is to use variant variables, and then a variable that had not been assigned a meaningful result would be empty. Trouble with that is likely to be the performance impact of the numerically intensive work I do.
« Last Edit: April 28, 2021, 01:17:25 pm by mtanner »

 

TinyPortal © 2005-2018