unit Myc.Mutable; interface uses System.SysUtils, Myc.Signals; type TMutable = 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); class operator Implicit(const A: IMutable): TMutable; overload; class operator Implicit(const A: TMutable): IMutable; overload; class property Null: IMutable read FNull; class function Construct(const Changing: TSignal; const Proc: TFunc): TMutable; overload; static; class function Constant(const Value: T): TMutable; overload; static; property Value: T read GetValue; property Changed: TSignal read GetChanged; end; TWriteable = record type IWriteable = interface(TMutable.IMutable) procedure SetValue(const Value: 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; overload; class operator Implicit(const A: TWriteable): IWriteable; overload; class function CreateWriteable: TWriteable; overload; static; class function CreateWriteable(const Init: T): TWriteable; overload; static; function Protect: TWriteable; function AsMutable: TMutable; property Value: T read GetValue write SetValue; property Changed: TSignal read GetChanged; end; TLazy = record type ILazy = interface {$REGION 'property access'} function GetChanged: TState; {$ENDREGION} function Update(var Value: 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); class operator Implicit(const A: ILazy): TLazy; overload; class operator Implicit(const A: TLazy): ILazy; overload; class property Null: ILazy read FNull; class function Constant(const Value: T): TLazy; overload; static; function Update(var Value: T): Boolean; inline; property Changed: TState read GetChanged; end; implementation uses Myc.Core.Mutable; { TMutable } constructor TMutable.Create(const AMutable: IMutable); begin if Assigned(AMutable) then FMutable := AMutable; end; class constructor TMutable.CreateClass; begin FNull := TMycConstMutable.Create(Default(T)); end; class function TMutable.Constant(const Value: T): TMutable; begin Result := TMycConstMutable.Create(Value); end; class function TMutable.Construct(const Changing: TSignal; const Proc: TFunc): TMutable; begin Result := TMycFuncMutable.Create(Changing, Proc); end; function TMutable.GetChanged: TSignal; begin Result := FMutable.Changed; end; function TMutable.GetValue: T; begin Result := FMutable.Value; end; class operator TMutable.Implicit(const A: TMutable): IMutable; begin Result := A.FMutable; end; class operator TMutable.Implicit(const A: IMutable): TMutable; begin Result.Create(A); end; class operator TMutable.Initialize(out Dest: TMutable); begin Dest.FMutable := FNull; end; { TWriteable } constructor TWriteable.Create(const AWriteable: IWriteable); begin FWriteable := AWriteable; Assert(Assigned(FWriteable)); end; function TWriteable.AsMutable: TMutable; begin Result.Create(FWriteable); end; class function TWriteable.CreateWriteable: TWriteable; begin Result := CreateWriteable(Default(T)); end; class function TWriteable.CreateWriteable(const Init: T): TWriteable; begin Result := TMycWriteableMutable.Create(Init); end; function TWriteable.GetChanged: TSignal; begin Result := FWriteable.Changed; end; function TWriteable.GetValue: T; begin Result := FWriteable.Value; end; function TWriteable.Protect: TWriteable; begin if not (FWriteable is TMycProtectedMutable) then Result := TMycProtectedMutable.Create(FWriteable) else Result := FWriteable; end; procedure TWriteable.SetValue(const Value: T); begin FWriteable.SetValue(Value); end; class operator TWriteable.Implicit(const A: IWriteable): TWriteable; begin Result.Create(A); end; class operator TWriteable.Implicit(const A: TWriteable): IWriteable; begin Result := A.FWriteable; end; { TLazy } constructor TLazy.Create(const ALazy: ILazy); begin FLazy := ALazy; end; class constructor TLazy.CreateClass; begin FNull := TMycConstLazy.Create(Default(T)); end; class function TLazy.Constant(const Value: T): TLazy; begin Result := TMycConstLazy.Create(Value); end; function TLazy.GetChanged: TState; begin Result := FLazy.Changed; end; function TLazy.Update(var Value: T): Boolean; begin Result := FLazy.Update(Value); end; class operator TLazy.Implicit(const A: TLazy): ILazy; begin Result := A.FLazy; end; class operator TLazy.Implicit(const A: ILazy): TLazy; begin Result.FLazy := A; end; class operator TLazy.Initialize(out Dest: TLazy); begin Dest.FLazy := FNull; end; end.