Files
MycLib/Src/Myc.Lazy.pas
T
Michael Schimmel 58ce84e567 Chart Control V1
2025-07-02 14:49:33 +02:00

258 lines
6.6 KiB
ObjectPascal

unit Myc.Lazy;
interface
uses
System.SysUtils,
Myc.Signals;
type
TMutable<T> = record
type
IMutable = interface
{$REGION 'property access'}
function GetChanged: TSignal;
function GetValue: T;
{$ENDREGION}
property Changed: TSignal read GetChanged;
property Value: T read GetValue;
end;
{$REGION 'private'}
strict private
class var
FNull: IMutable;
class constructor CreateClass;
private
FMutable: IMutable;
function GetChanged: TSignal; inline;
function GetValue: T; inline;
{$ENDREGION}
public
constructor Create(const AMutable: IMutable);
class operator Initialize(out Dest: TMutable<T>);
class operator Implicit(const A: IMutable): TMutable<T>; overload;
class operator Implicit(const A: TMutable<T>): IMutable; overload;
class property Null: IMutable read FNull;
class function Construct(const Changing: TSignal; const Proc: TFunc<T>): TMutable<T>; overload; static;
property Value: T read GetValue;
property Changed: TSignal read GetChanged;
end;
TWriteable<T> = record
type
IWriteable = interface(TMutable<T>.IMutable)
procedure SetValue(const Value: T);
function Exchange(const Value: T): T;
end;
{$REGION 'private'}
private
FWriteable: IWriteable;
function GetChanged: TSignal; inline;
function GetValue: T; inline;
procedure SetValue(const Value: T);
{$ENDREGION}
public
constructor Create(const AWriteable: IWriteable);
class operator Implicit(const A: IWriteable): TWriteable<T>; overload;
class operator Implicit(const A: TWriteable<T>): IWriteable; overload;
class function CreateWriteable: TWriteable<T>; overload; static;
class function CreateWriteable(const Init: T): TWriteable<T>; overload; static;
function Protect: TWriteable<T>;
property Value: T read GetValue write SetValue;
property Changed: TSignal read GetChanged;
end;
TLazy<T> = record
type
ILazy = interface
{$REGION 'property access'}
function GetChanged: TState;
{$ENDREGION}
function Pop(out Res: T): Boolean;
property Changed: TState read GetChanged;
end;
{$REGION 'private'}
strict private
class var
FNull: ILazy;
class constructor CreateClass;
private
FLazy: ILazy;
function GetChanged: TState; inline;
{$ENDREGION}
public
constructor Create(const ALazy: ILazy);
class operator Initialize(out Dest: TLazy<T>);
class operator Implicit(const A: ILazy): TLazy<T>; overload;
class operator Implicit(const A: TLazy<T>): ILazy; overload;
class function Construct(const Changing: TSignal.ISignal; const Proc: TFunc<T>): TLazy<T>; overload; static;
class function Construct(const Mutable: TMutable<T>): TLazy<T>; overload; static;
class property Null: ILazy read FNull;
function Pop(out Res: T): Boolean; inline;
property Changed: TState read GetChanged;
end;
implementation
uses
Myc.Core.Lazy;
{ TMutable<T> }
constructor TMutable<T>.Create(const AMutable: IMutable);
begin
if Assigned(AMutable) then
FMutable := AMutable;
end;
class constructor TMutable<T>.CreateClass;
begin
FNull := TMycNullMutable<T>.Create;
end;
class function TMutable<T>.Construct(const Changing: TSignal; const Proc: TFunc<T>): TMutable<T>;
begin
Result := TMycFuncMutable<T>.Create(Changing, Proc);
end;
function TMutable<T>.GetChanged: TSignal;
begin
Result := FMutable.Changed;
end;
function TMutable<T>.GetValue: T;
begin
Result := FMutable.Value;
end;
class operator TMutable<T>.Implicit(const A: TMutable<T>): IMutable;
begin
Result := A.FMutable;
end;
class operator TMutable<T>.Implicit(const A: IMutable): TMutable<T>;
begin
Result.Create(A);
end;
class operator TMutable<T>.Initialize(out Dest: TMutable<T>);
begin
Dest.FMutable := FNull;
end;
{ TLazy<T> }
constructor TLazy<T>.Create(const ALazy: ILazy);
begin
if Assigned(ALazy) then
FLazy := ALazy;
end;
class function TLazy<T>.Construct(const Changing: TSignal.ISignal; const Proc: TFunc<T>): TLazy<T>;
begin
Result := TMycFuncLazy<T>.Create(Changing, Proc);
end;
class constructor TLazy<T>.CreateClass;
begin
FNull := TMycNullLazy<T>.Create;
end;
class function TLazy<T>.Construct(const Mutable: TMutable<T>): TLazy<T>;
begin
var cap := Mutable;
Result := TMycFuncLazy<T>.Create(cap.Changed, function: T begin exit(Mutable.Value) end);
end;
function TLazy<T>.GetChanged: TState;
begin
Result := FLazy.Changed;
end;
function TLazy<T>.Pop(out Res: T): Boolean;
begin
Result := FLazy.Pop(Res);
end;
class operator TLazy<T>.Implicit(const A: ILazy): TLazy<T>;
begin
Result.Create(A);
end;
class operator TLazy<T>.Implicit(const A: TLazy<T>): ILazy;
begin
Result := A.FLazy;
end;
class operator TLazy<T>.Initialize(out Dest: TLazy<T>);
begin
Dest.FLazy := FNull;
end;
{ TWriteable<T> }
constructor TWriteable<T>.Create(const AWriteable: IWriteable);
begin
FWriteable := AWriteable;
Assert(Assigned(FWriteable));
end;
class function TWriteable<T>.CreateWriteable: TWriteable<T>;
begin
Result := CreateWriteable(Default(T));
end;
class function TWriteable<T>.CreateWriteable(const Init: T): TWriteable<T>;
begin
Result := TMycWriteableMutable<T>.Create(Init);
end;
function TWriteable<T>.GetChanged: TSignal;
begin
Result := FWriteable.Changed;
end;
function TWriteable<T>.GetValue: T;
begin
Result := FWriteable.Value;
end;
function TWriteable<T>.Protect: TWriteable<T>;
begin
if not (FWriteable is TMycProtectedMutable<T>) then
Result := TMycProtectedMutable<T>.Create(FWriteable)
else
Result := FWriteable;
end;
procedure TWriteable<T>.SetValue(const Value: T);
begin
FWriteable.SetValue(Value);
end;
class operator TWriteable<T>.Implicit(const A: IWriteable): TWriteable<T>;
begin
Result.Create(A);
end;
class operator TWriteable<T>.Implicit(const A: TWriteable<T>): IWriteable;
begin
Result := A.FWriteable;
end;
end.