type TRef<AT, RT> = reference to function(X: AT): RT; var Negate: TRef<TRef<Integer, Boolean>, TRef<Integer, Boolean>>; IsOdd, IsEven: TRef<Integer, Boolean>; begin // , IsOdd := function(X: Integer): Boolean begin Result := X mod 2 <> 0; end; // Negate := function(F: TRef<Integer, Boolean>): TRef<Integer, Boolean> begin Result := function(X: Integer): Boolean begin Result := not F(X); end; end; // IsEven := Negate(IsOdd); WriteLn(IsOdd(4)); // => False WriteLn(IsEven(4)); // => True end;
type TOneArgRef = reference to function(X: Single): Single; TTwoArgRef = reference to function(X, Y: Single): Single; TCompose = reference to function(F: TOneArgRef; G: TTwoArgRef): TTwoArgRef; var Compose: TCompose; Square: TOneArgRef; Half: TOneArgRef; Sum: TTwoArgRef; SquareOfSum: TTwoArgRef; HalfSum: TTwoArgRef; begin // "" Compose := function(F: TOneArgRef; G: TTwoArgRef): TTwoArgRef begin Result := function(X, Y: Single): Single begin Result := F(G(X, Y)); end; end; // : // 1. Square := function(X: Single): Single begin Result := X * X; end; // 2. Half := function(X: Single): Single begin Result := X / 2; end; // 3. Sum := function(X, Y: Single): Single begin Result := X + Y; end; // " " SquareOfSum := Compose(Square, Sum); // "" HalfSum := Compose(Half, Sum); WriteLn(SquareOfSum(2.0, 3.0)); // => 25.0 WriteLn(HalfSum(3.0, 7.0)); // => 5.0 end;
type TManyArgRef = reference to function(Args: TArray<Double>): Double; TBindRef = reference to function(Args: TArray<Double>; F: TManyArgRef): TManyArgRef; var BindLeft: TBindRef; Calc, Partial: TManyArgRef; begin // , Args // F . BindLeft := function(Args: TArray<Double>; F: TManyArgRef): TManyArgRef var StoredArgs: TArray<Double>; begin StoredArgs := Args; Result := function(Args: TArray<Double>): Double begin Result := F(StoredArgs + Args); end; end; // // Calc := function(A: TArray<Double>): Double begin Result := A[0] * (A[1] - A[2]); end; // Partial := BindLeft([2, 3], Calc); // WriteLn(Partial([4])); // => -2.0 // Partial Calc([2, 3, 4]) end;
BindRight := function(Args: TArray<Double>; F: TManyArgRef): TManyArgRef var StoredArgs: TArray<Double>; begin StoredArgs := Args; Result := function(Args: TArray<Double>): Double begin Result := F(Args + StoredArgs); // end; end;
type TOneArgRef = reference to function(X: Double): Double; TThreeArgRef = reference to function(X, Y, Z: Double): Double; TSecondStepRef = reference to function(X: Double): TOneArgRef; TFirstStepRef = reference to function(X: Double): TSecondStepRef; TCurryRef = reference to function(F: TThreeArgRef): TFirstStepRef; var Curry: TCurryRef; Calc: TThreeArgRef; F1: TFirstStepRef; F2: TSecondStepRef; F3: TOneArgRef; Re: Double; begin // Curry := function(F: TThreeArgRef): TFirstStepRef begin Result := function(A: Double): TSecondStepRef begin Result := function(B: Double): TOneArgRef begin Result := function(C: Double): Double begin Result := F(A, B, C); end; end; end; end; // , // Calc := function(A, B, C: Double): Double begin Result := A + B + C; end; // Calc, F1 := Curry(Calc); F2 := F1(1); F3 := F2(2); Re := F3(3); WriteLn(Re); // => 6.0 end;
type TRef<AT, RT> = reference to function(Args: AT): RT; TCalc<T> = reference to function(X, Y, Z: T): T; var Curry: TRef<TCalc<Double>,TRef<Double,TRef<Double,TRef<Double,Double>>>>; Calc: TCalc<Double>; begin // Curry := function(F: TCalc<Double>): TRef<Double,TRef<Double,TRef<Double,Double>>> begin Result := function(A: Double): TRef<Double,TRef<Double,Double>> begin Result := function(B: Double): TRef<Double,Double> begin Result := function(C: Double): Double begin Result := F(A, B, C); end; end; end; end; // Calc := function(A, B, C: Double): Double begin Result := A + B + C; end; // WriteLn(Curry(Calc)(1)(2)(3)); // => 6.0 end;
type TRef = reference to function(X: Integer): Double; TMemoize = reference to function(F: TRef): TRef; var Memoize: TMemoize; Calc: TRef; MemoizedCalc: TRef; begin // Memoize Memoize := function(F: TRef): TRef var Cache: ICache<Integer, Double>; begin Cache := TCache<Integer, Double>.Create; Result := function(X: Integer): Double begin // ... if not Cache.TryGetValue(X, Result) then begin Result := F(X); // ... Cache.Add(X, Result); // end; end; end; // , Calc := function(X: Integer): Double var I: Integer; begin Result := 0; for I := 1 to High(Word) do Result := Result + Ln(I) / Sin(I) * X; end; // Calc MemoizedCalc := Memoize(Calc); end;
interface uses Generics.Collections; type // ICache<TKey, TValue> = interface function TryGetValue(Key: TKey; out Value: TValue): Boolean; procedure Add(Key: TKey; Value: TValue); end; TCache<TKey, TValue> = class(TInterfacedObject, ICache<TKey, TValue>) private FDictionary: TDictionary<TKey, TValue>; public constructor Create; destructor Destroy; override; function TryGetValue(Key: TKey; out Value: TValue): Boolean; procedure Add(Key: TKey; Value: TValue); end; implementation constructor TCache<TKey, TValue>.Create; begin FDictionary := TDictionary<TKey, TValue>.Create; end; destructor TCache<TKey, TValue>.Destroy; begin FDictionary.Free; inherited; end; procedure TCache<TKey, TValue>.Add(Key: TKey; Value: TValue); begin FDictionary.Add(Key, Value); end; function TCache<TKey, TValue>.TryGetValue(Key: TKey; out Value: TValue): Boolean; begin Result := FDictionary.TryGetValue(Key, Value); end;
uses SysUtils, DateUtils; var I: Integer; Time: TDateTime; Ms1, Ms2: Int64; Res1, Res2: Double; begin Res1 := 0; Res2 := 0; // Time := Now; for I := 1 to 1000 do Res1 := Res1 + Calc(I mod 100); Ms1 := MilliSecondsBetween(Now, Time); // Time := Now; for I := 1 to 1000 do Res2 := Res2 + MemoizedCalc(I mod 100); Ms2 := MilliSecondsBetween(Now, Time); WriteLn(Res1 = Res2); // => True WriteLn(Ms1 > Ms2); // => True end;
type TRef = reference to function: Cardinal; TGenRef = reference to function: TRef; var FibGen, FactGen: TGenRef; FibVal, FactVal: TRef; I: Integer; begin // -, FibGen := function: TRef var X, Y: Cardinal; begin X := 0; Y := 1; Result := function: Cardinal begin Result := Y; Y := X + Y; X := Result; end; end; // -, FactGen := function: TRef var X, Y: Cardinal; begin X := 1; Y := 1; Result := function: Cardinal begin Result := Y; Y := Y * X; Inc(X); end; end; // - . // Delphi, . FibVal := FibGen(); FactVal := FactGen(); for I := 1 to 10 do WriteLn(FibVal, #9, FactVal); end;
type TStringRef = reference to function: string; TEachLineRef = reference to function(S: string): TStringRef; TArgMap = reference to function(S: string): string; TMap = reference to function(A: TStringRef; F: TArgMap): TStringRef; TArgSelect = reference to function(S: string): Boolean; TSelect = reference to function(A: TStringRef; F: TArgSelect): TStringRef; const // , TEXT = '#comment ' + sLineBreak + '' + sLineBreak + ' hello' + sLineBreak + ' world ' + sLineBreak + ' quit ' + sLineBreak + ' unreached'; var EachLine: TEachLineRef; Map: TMap; Select: TSelect; Lines, Trimmed, Nonblank: TStringRef; S: string; begin // , . EachLine := function(S: string): TStringRef begin Result := function: string begin Result := S.Substring(0, S.IndexOf(sLineBreak)); S := S.Substring(S.IndexOf(sLineBreak) + 1); end; end; // , , - F A Map := function(A: TStringRef; F: TArgMap): TStringRef begin Result := function: string begin Result := F(A); end; end; // -, A, F(A) = True Select := function(A: TStringRef; F: TArgSelect): TStringRef begin Result := function: string begin repeat Result := A; until F(Result); end; end; // : // Lines := EachLine(TEXT); // Trimmed := Map(Lines, function(S: string): string begin Result := S.Trim; end); // , Nonblank := Select(Trimmed, function(S: string): Boolean begin Result := (S.Length > 0) and (S[1] <> '#'); end); // , // , 'quit' repeat S := Nonblank; if S = 'quit' then Break; WriteLn(S); until False; end;
Source: https://habr.com/ru/post/244945/
All Articles