How to implement Yield in Delphi

Delphi programming language has all the guts to compete with C# and Java. For example, you can quite easily implement C# yield return in Delphi:

Example of yield return from C# reference:

public class PowersOf2
{
    static void Main()
    {
        // Display powers of 2 up to the exponent of 8:
        foreach (int i in Power(2, 8))
        {
            Console.Write("{0} ", i);
        }
    }

    public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
    {
        int result = 1;

        for (int i = 0; i < exponent; i++)
        {
            result = result * number;
            yield return result;
        }
    }

    // Output: 2 4 8 16 32 64 128 256
}

Same code in Delphi:

program PowersOf2;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.Yield in 'System.Yield.pas';

function Power(Number: Integer; Exponent: Integer): TYieldEnumerable<Integer>;
begin
  Result := TYieldEnumerable<Integer>.Create(
    procedure(Yield: TYield<Integer>)
    var
      RetVal: Integer;
      i: Integer;
    begin
      RetVal := 1;
      for i := 1 to Exponent do
      begin
        RetVal := RetVal * Number;
        Yield(RetVal);
      end;
    end);
end;

var
  i: Integer;
begin
  for i in Power(2, 8) do
  begin
    Writeln(i);
  end;
  Readln;
end.

System.Yield is a unit that I have created that implements the magic via Delphi enumerators and WinAPI fibers. Sure thing, people were implementing yield return in Delphi before, but they were doing this either via assembler by manipulating stack frames (problems with exceptions) or were bundling small yield return feature with giant libraries.

The unit of mine is very small (125+ lines of code), it does not have any other dependencies except WinAPI.Windows unit, it correctly handles exceptions and nested yields.

The only problem is that this unit is Windows only -- I am not aware if fibers API exists on MacOSX.

AttachmentSize
DelphiYield.zip6.55 KB

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.