Forum > General
Nullable and Immutable types
Peter H:
--- Quote ---Well, de facto the FHasValue of the nullable types is zeroed, so virtually “initialized” with false, thus it isn’t actually required, but nevertheless clean programming.
--- End quote ---
I do not see where "FHasvalue" is zeroed in this example. If the Nullable record is instantiated as local variable, then it occupies random uninitialized memory and there must be some code to initialize it.
I do not know, if global static memory is zeroed, but this might be different on different OS, or the debugger or linker or loader could do it or not do it, so I would not rely on this.
jamie:
FPC already does some of this stuff in a way that I guess you could call it a auto initialize
Var
MyVariable :ABasicaType = 0;
begin
your code..
This of course will zero the variable each time the function is entered .
Then you have the Advanced records which I think was already mentioned here which comes with initialize and finalize constructor options but may only be supported in 3.3 or could be 3.2
But in any case this should allow for managed code to do what ever is needed upon entry to the function.
am I off track here ?
Warfley:
I created my own Optional type some time ago and used management operators to initialize it (Mode Delphi):
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type TEmptyOptional = record; { TOptional } TOptional<T> = record public type PT = ^T; private FHasValue: Boolean; FValue: T; class operator Initialize(var a: TOptional<T>); public constructor Create(constref AValue: T); function ValuePtr: PT; inline; function Value: T; inline; function GetOrDefault(constref def: T): T; class operator Implicit(constref AValue: T): TOptional<T>; inline; class operator Explicit(constref AValue: T): TOptional<T>; inline; class operator Implicit(constref AValue: TEmptyOptional): TOptional<T>; inline; class operator Explicit(constref AValue: TEmptyOptional): TOptional<T>; inline; class operator Implicit(constref opt: TOptional<T>): Boolean; inline; class operator Explicit(constref opt: TOptional<T>): Boolean; inline; class operator LogicalNot(constref opt: TOptional<T>): Boolean; inline; property HasValue: Boolean read FHasValue; class function Empty: TOptional<T>; static; inline; end; function EmptyOptional: TEmptyOptional; inline; implementation { TOptional } class operator TOptional<T>.Initialize(var a: TOptional<T>);begin a.FHasValue := False;end; constructor TOptional<T>.Create(constref AValue: T);begin FHasValue := True; FValue := AValue;end; function TOptional<T>.ValuePtr: PT;begin If not HasValue then raise ENoValuePresentException.Create('Trying to access value of an empty optional'); Result := @FValue;end; function TOptional<T>.Value: T;begin If not HasValue then raise ENoValuePresentException.Create('Trying to access value of an empty optional'); Result := FValue;end; function TOptional<T>.GetOrDefault(constref def: T): T;begin If HasValue then Result := FValue else Result := def;end; class operator TOptional<T>.Implicit(constref AValue: T): TOptional<T>;begin Result.FHasValue := True; Result.FValue := AValue;end; class operator TOptional<T>.Explicit(constref AValue: T): TOptional<T>;begin Result.FHasValue := True; Result.FValue := AValue;end; class operator TOptional<T>.Implicit(constref AValue: TEmptyOptional): TOptional <T>;begin Result.FHasValue := False;end; class operator TOptional<T>.Explicit(constref AValue: TEmptyOptional): TOptional <T>;begin Result.FHasValue := False;end; class operator TOptional<T>.Implicit(constref opt: TOptional<T>): Boolean;begin Result := opt.HasValue;end; class operator TOptional<T>.Explicit(constref opt: TOptional<T>): Boolean;begin Result := opt.HasValue;end; class operator TOptional<T>.LogicalNot(constref opt: TOptional<T>): Boolean;begin Result := not opt.HasValue;end; class function TOptional<T>.Empty: TOptional<T>;begin Result.FHasValue := False;end; function EmptyOptional: TEmptyOptional;begin // Nothing to do hereend;
The main difference to the TNullable example (except for the management initialization) is that it does not take pointers to be nullable, as this requires a runtime check, but can be cleared by using a custom dummy type TEmptyOptional, which is generated via the function emptyOptional, i.e.:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---myOpt := EmptyOptional;It also has some more casts that make it's usage easier (like implicit cast to bool to check for it's existance)
If you want to make that type single assignment readonly you can do the following:
1. remove the ValuePtr function, as this allows writing to the value without our access.
2. Implement the copy class operator as follows:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---class operator TOptional<T>.Copy(constref aSrc: TOptional<T>; var aDst: TOptional<T>);begin if aDst then raise EAlreadyAssignedQuestion.Create('Trying to override already assigned optional'); aDst.FHasValue := aSrc.FHasValue; if aSrc then aDst.FValue := aSrc.FValue;end;
Note: you also need to define EAlreadyAssignedQuestion as exception type:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---EAlreadyAssignedQuestion = class(Exception);
But this is only a runtime check and is not enforced on compiletime
Peter H:
@Jamie
I tried this, gives a compile error:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---Type testtype = record a:integer; end; procedure TForm1.btnDisconnectClick(Sender: TObject);var a:testtype = 0;.....
Is a modeswitch required?
(I use {$mode objfpc}{$H+} FPC 3.3.1)
Warfley:
--- Quote from: Peter H on January 03, 2021, 01:49:28 am ---@Jamie
I tried this, gives a compile error:
--- End quote ---
I think the syntax is this:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type TTestRec = record A, B: Integer; end; var test: TTestRec = (A: 42; B: 32);
Navigation
[0] Message Index
[#] Next page
[*] Previous page