Forum > General

Nullable and Immutable types

<< < (2/4) > >>

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

Go to full version