Snippets

Created by Stefan Glienke

File snippet.txt Added

  • Ignore whitespace
  • Hide word diff
+program RangeDemo;
+
+uses
+  SysUtils;
+
+type
+  // see https://docs.python.org/3/library/stdtypes.html#range
+  TRange = record
+  private
+    fStart, fStop, fStep: Integer;
+    type
+      TEnumerator = record
+      private
+        fStop, fStep: Integer;
+        fCurrent: Integer;
+      public
+        function MoveNext: Boolean; inline;
+        property Current: Integer read fCurrent;
+      end;
+  public
+    constructor Create(stop: Integer); overload;
+    constructor Create(start, stop: Integer; step: Integer = 1); overload;
+
+    function Equals(const other: TRange): Boolean;
+    function GetEnumerator: TEnumerator; inline;
+
+    class operator Equal(const left, right: TRange): Boolean; inline;
+    class operator NotEqual(const left, right: TRange): Boolean; inline;
+  end;
+
+function Range(stop: Integer): TRange; overload; inline;
+begin
+  Result := TRange.Create(stop);
+end;
+
+function Range(start, stop: Integer; step: Integer = 1): TRange; overload; inline;
+begin
+  Result := TRange.Create(start, stop, step);
+end;
+
+{ TRange }
+
+constructor TRange.Create(stop: Integer);
+begin
+  fStart := 0;
+  fStop := stop;
+  fStep := 1;
+end;
+
+constructor TRange.Create(start, stop, step: Integer);
+begin
+  fStart := start;
+  fStop := stop;
+  fStep := step;
+end;
+
+class operator TRange.Equal(const left, right: TRange): Boolean;
+begin
+  Result := left.Equals(right);
+end;
+
+function TRange.Equals(const other: TRange): Boolean;
+var
+  left, right: TEnumerator;
+begin
+  left := GetEnumerator;
+  right := other.GetEnumerator;
+  while left.MoveNext do
+    if not (right.MoveNext and (left.Current = right.Current)) then
+      Exit(False);
+  Result := not right.MoveNext;
+end;
+
+function TRange.GetEnumerator: TEnumerator;
+begin
+  Result.fStop := fStop;
+  Result.fStep := fStep;
+  Result.fCurrent := fStart - fStep;
+end;
+
+class operator TRange.NotEqual(const left, right: TRange): Boolean;
+begin
+  Result := not left.Equals(right);
+end;
+
+{ TRange.TEnumerator }
+
+function TRange.TEnumerator.MoveNext: Boolean;
+begin
+  Inc(fCurrent, fStep);
+  if fStep > 0 then
+    Result := fCurrent < fStop
+  else
+    Result := fCurrent > fStop;
+end;
+
+procedure List(const r: TRange);
+var
+  s: string;
+  i: Integer;
+begin
+  for i in r do
+  begin
+    if s <> '' then
+      s := s + ', ';
+    s := s + IntToStr(i);
+  end;
+  s := '[' + s + ']';
+  Writeln(s);
+end;
+
+begin
+  List(Range(10));
+  List(Range(1, 11));
+  List(Range(0, 30, 5));
+  List(Range(0, 10, 3));
+  List(range(0, -10, -1));
+  List(Range(0));
+  List(Range(1, 0));
+
+  Assert(Range(0) = Range(2, 1, 3));
+  Assert(Range(0, 3, 2) = Range(0, 4, 2));
+
+  ReadLn;
+end.
HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.