Snippets

Stefan Glienke Immutable array

Created by Stefan Glienke
program ImmutableArray;

{$APPTYPE CONSOLE}

uses
  Generics.Defaults,
  SysUtils;

type
  TImmutableArray<T> = record
  strict private
    fData: TArray<T>;
    function IndexOf(const value: T): Integer;
  public
    class operator Implicit(const data: TArray<T>): TImmutableArray<T>; inline;

    function Add(const value: T): TArray<T>;
    function Remove(const value: T): TArray<T>;

    property Data: TArray<T> read fData;
  end;

{ TImmutableArray<T> }

class operator TImmutableArray<T>.Implicit(
  const data: TArray<T>): TImmutableArray<T>;
begin
  Result.fData := data;
end;

function TImmutableArray<T>.Add(const value: T): TArray<T>;
var
  len: Integer;
begin
  Result := fData;
  len := Length(Result);
  SetLength(Result, len + 1);
  Result[len] := value;
end;

function TImmutableArray<T>.Remove(const value: T): TArray<T>;
var
  i, n: Integer;
begin
  i := IndexOf(value);
  if i < 0 then
    Exit(fData);
  n := High(fData);
  if n = 0 then
    Exit(nil);
  if i = n then
    Exit(Copy(fData, 0, i));
  Result := Copy(fData);
  Result[i] := Default(T);
  Move(Result[i + 1], Result[i], (n - i) * SizeOf(T));
  SetLength(Result, n);
end;

function TImmutableArray<T>.IndexOf(const value: T): Integer;
var
  i: Integer;
  comparer: IEqualityComparer<T>;
begin
  comparer := TEqualityComparer<T>.Default;
  for i := 0 to High(fData) do
    if comparer.Equals(fData[i], value) then
      Exit(i);
  Result := -1;
end;

procedure Main;
var
  a, b, c: TImmutableArray<Integer>;
  i: Integer;
begin
  a := TArray<Integer>.Create(1, 2, 3, 4);
  b := a;
  c := a.Add(5);
  a := TArray<Integer>.Create(1, 2);
  c := a.Remove(2);
  b := c.Remove(1);

  for i in a.Data do
    Writeln(i);
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

Comments (0)

HTTPS SSH

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