uses System.SysUtils, System.Diagnostics,
System.Generics.Collections;
function Fibonacci(X: Integer): Integer;
begin
if X <= 2 then
Exit(1);
Result := Fibonacci(X - 1) +
Fibonacci(X - 2);
end;
function Memoize(
Fun: TFunc<Integer, Integer>):
TFunc<Integer, Integer>;
var
Memo: TDictionary<Integer, Integer>;
begin
//the cache is captured by the closure
Memo := TDictionary<Integer, Integer>.Create;
Result := function(X: Integer): Integer
begin
if not Memo.TryGetValue(X, Result) then
begin
Result := Fun(X);
Memo.Add(X, Result);
end;
end;
end;
var
MemFibonacci: TFunc<Integer, Integer>;
Watch: TStopwatch;
I: Integer;
begin
MemFibonacci := Memoize(Fibonacci);
for I := 1 to 2 do
begin
Watch := TStopwatch.StartNew;
WriteLn(I, ': f37 is ', MemFibonacci(37));
WriteLn(I, ': milliseconds is ',
Watch.ElapsedMilliseconds);
end;
//the second call is instant:
//the value comes from the cache
Watch := TStopwatch.StartNew;
WriteLn('f38 is ', MemFibonacci(38));
WriteLn('milliseconds is ',
Watch.ElapsedMilliseconds);
//f38 is 39088169
end.