Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
Delphi 10 Seattle Enterprise
|
AW: Brauche Idee, um immer wiederkehrenden Quellcode zu vermeiden.
10. Feb 2015, 09:54
Mit den Anonymen Methoden kann man schon sehr lustige Dinge anstellen:
Delphi-Quellcode:
type
Closure = record
class function Memoize<T, TResult>( AFunc: TFunc<T, TResult>; AEqualityComparer: IEqualityComparer<T> = nil ): TFunc<T, TResult>; static;
end;
class function Closure.Memoize<T, TResult>( AFunc: TFunc<T, TResult>; AEqualityComparer: IEqualityComparer<T> ): TFunc<T, TResult>;
var
LDict: AutoRef<TDictionary<T, TResult>>; { AutoRef kapselt eine Instanz in einem Interface und sorgt für die automatische Freigabe }
begin
LDict := TDictionary<T, TResult>.Create( AEqualityComparer );
Result := function( Arg: T ): TResult
begin
if not LDict.Reference.TryGetValue( Arg, Result )
then
begin
Result := AFunc( Arg );
LDict.Reference.Add( Arg, Result );
end;
end;
end;
So, wozu braucht man das?
Delphi-Quellcode:
function fibonacci( n: Int64 ): Int64;
begin
if n < 2
then
Result := n
else
Result := fibonacci( n - 1 ) + fibonacci( n - 2 );
end;
function fibonacci_memoize( n: Int64 ): Int64;
var
fibonacci: TFunc<Int64, Int64>;
begin
fibonacci := Closure.Memoize<Int64, Int64>(
function( n: Int64 ): Int64
begin
if n < 2
then
Result := n
else
Result := fibonacci( n - 1 ) + fibonacci( n - 2 );
end );
Result := fibonacci( n );
end;
procedure memoize_test;
var
LFibN, LFibResult: Int64;
LStopwatch: TStopwatch;
begin
LFibN := 40;
LStopwatch := TStopwatch.StartNew;
LFibResult := fibonacci( LFibN ); // Standard Umsatzung
LStopwatch.Stop;
Writeln( Format( 'fibonacci(%d) = %d (%dms)', [LFibN, LFibResult, LStopwatch.ElapsedMilliseconds] ) );
LStopwatch := TStopwatch.StartNew;
LFibResult := fibonacci_memoize( LFibN ); // mit Closure.Memoize
LStopwatch.Stop;
Writeln( Format( 'fibonacci(%d) = %d (%dms)', [LFibN, LFibResult, LStopwatch.ElapsedMilliseconds] ) );
end;
Beide berechnen exakt die gleichen Werte, spannend sind jetzt die Laufzeiten
Code:
fibonacci(40) = 102334155 (1101ms)
fibonacci(40) = 102334155 (0ms)
fibonacci(100) = (dauert mir zu lange)
fibonacci(100) = 3736710778780434371 (0ms)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
|
|
Zitat
|