# Set

Deutsch (de) English (en) suomi (fi) français (fr) русский (ru)

## Introduction

A Set encodes many values from an enumeration into an Ordinal type.

For example let's consider this enumeration:

  TSpeed = (spVerySlow,spSlow,spAVerage,spFast,spVeryFast);

And this set:

  TPossibleSpeeds = set of TSpeed

Constant instances of TPossibleSpeeds can be defined using brackets to hold set elements:

  const
RatherSlow = [spVerySlow,spSlow];
RatherFast = [spFast,spVeryFast];

RatherSlow and RatherFast are some Set of TSpeed.

## Manipulating sets

Two functions defined in the RTL System unit are used to manipulate a set: Include(ASet,AValue) and Exclude(ASet,AValue).

  var
SomeSpeeds: TPossibleSpeeds;
begin
SomeSpeeds := [];
Include(SomeSpeeds,spVerySlow);
Include(SomeSpeeds,spVeryFast);
end;

Sets cannot be directly manipulated if they are published. You usually have to make a local copy, change the local copy and then to call the setter.

  procedure TSomething.DoSomething(Sender: TFarObject);
var
LocalCopy: TPossibleSpeeds;
begin
LocalCopy := Sender.PossibleSpeeds; // getter to local
Include(LocalCopy,spVerySlow);
Sender.PossibleSpeeds := LocalCopy; // local to setter.
end;

The Keyword In is also used to test if a value is in a set. It's usually used in this fashion:

  var
CanBeSlow: Boolean;
const
SomeSpeeds = [Low(TSpeed)..High(TSpeed)];
begin
CanBeSlow := (spVerySlow in SomeSpeeds) or (spSlow in SomeSpeeds);
end;

Sets can be used to create bitmasks as shown in the example.

(*
The set [FLAG_A, FLAG_C] will be stored like this:

TFlags :   0000'0101
│││
FLAG_C ──────────┘││
FLAG_B ───────────┘│
FLAG_A ────────────┘
*)

type
TFlag = (FLAG_A, FLAG_B, FLAG_C);
TFlags = set of TFlag;

var
Flags: TFlags;

[..]
Flags:= [FLAG_A, FLAG_C];
if FLAG_A in Flags then ..  // check FLAG_A is set in flags variable