unit Myc.Core.Lazy; interface uses System.SysUtils, Myc.Signals, Myc.Lazy; type TMycNullLazy = class(TInterfacedObject, IMycLazy) protected function GetChanged: TState; public function Pop(out Res: T): Boolean; end; TMycLazyBase = class(TInterfacedObject, IMycLazy) strict private FChanged: TFlag; FChangeState: TSignal.TSubscription; function GetChanged: TState; protected function GetValue: T; virtual; abstract; public constructor Create(const AChanged: TState); destructor Destroy; override; function Pop(out Res: T): Boolean; end; TMycFuncLazy = class(TMycLazyBase) private FProc: TFunc; protected function GetValue: T; override; public constructor Create(const AChanged: TState; const AProc: TFunc); end; TMycChainedLazy = class(TMycLazyBase) private FValue: IMycLazy; protected function GetValue: T; override; public constructor Create(const AValue: IMycLazy); end; implementation { TMycNullLazy } function TMycNullLazy.GetChanged: TState; begin Result := TState.Null; end; function TMycNullLazy.Pop(out Res: T): Boolean; begin Res := Default(T); Result := true; end; { TMycLazyBase } constructor TMycLazyBase.Create(const AChanged: TState); begin inherited Create; FChanged := TFlag.CreateFlag; FChangeState := AChanged.Subscribe(FChanged); end; destructor TMycLazyBase.Destroy; begin FChangeState.Unsubscribe; inherited; end; function TMycLazyBase.GetChanged: TState; begin Result := FChanged.State; end; function TMycLazyBase.Pop(out Res: T): Boolean; begin Result := FChanged.State.IsSet; if Result then begin Res := GetValue; FChanged.Reset; end; end; { TMycFuncLazy } constructor TMycFuncLazy.Create(const AChanged: TState; const AProc: TFunc); begin inherited Create(AChanged); FProc := AProc; Assert(Assigned(FProc)); end; function TMycFuncLazy.GetValue: T; begin Result := FProc(); end; { TMycChainedLazy } constructor TMycChainedLazy.Create(const AValue: IMycLazy); begin inherited Create(AValue.Changed); FValue := AValue; end; function TMycChainedLazy.GetValue: T; begin if not FValue.Pop(Result) then raise Exception.Create('Lazy chain already popped'); end; end.