type CharSet = set of char; var X, Y, Z: CharSet; begin X := ['a','b','c', 'x'..'z']; println(X); Y := ['c','d','e']; println(Y); println('a' in X); println('a' in Y); Z := X + Y; println(Z); Z := X - Y; println(Z); Z := X * Y; println(Z); end.
This code is based on implementation in Amigo language:
type ByteSetRange = 0..31; class ByteSet<T> { var FBits: RangedArray<ByteSetRange, byte> fn constructor() { FBits = new RangedArray<ByteSetRange, byte>(); } fn ToString(): string { var s: string = "["; for (var i = 0; i < 255; i++) { if (Contains(this, i as T)) { s += to_string(i as T) + ","; } } if (s.Contains(",")) s = s.Remove(s.Length - 1, 1); s += "]"; } static fn Include(Set: ByteSet<T>, value: T) { var v = value as byte; var N = v / 8; var V = v % 8; V = 1 << V; Set.FBits[N] = Set.FBits[N] | V; } static fn Exclude(Set: ByteSet<T>, value: T) { var v = value as byte; var N = v / 8; var V = v % 8; V = 1 << V; V = ~V; Set.FBits[N] = Set.FBits[N] & V; } static fn Contains(Set: ByteSet<T>, value: T): bool { var v = value as byte; var N = v / 8; var V = v % 8; V = 1 << V; Set.FBits[N] & V != 0; } static fn implicit (V: Tuple): ByteSet<T> { var R = new ByteSet<T>(); for (var x in V) ByteSet<T>.Include(R, x); R; } static fn operator+ (X, Y: ByteSet<T>): ByteSet<T> { var R = new ByteSet<T>(); for (var i = 0; i < 31; i++) R.FBits[i] = X.FBits[i] | Y.FBits[i]; R; } static fn operator* (X, Y: ByteSet<T>): ByteSet<T> { var R = new ByteSet<T>(); for (var i = 0; i < 31; i++) R.FBits[i] = X.FBits[i] & Y.FBits[i]; R; } static fn operator- (X, Y: ByteSet<T>): ByteSet<T> { var R = new ByteSet<T>(); for (var i = 0; i < 31; i++) R.FBits[i] = X.FBits[i] & ~Y.FBits[i]; R; } } type CharSet = ByteSet<char> var X: CharSet = ['a','b','c', 'x'..'z']; // extended tuple literal println(X); var Y: CharSet = ['c','d','e']; println(Y); println(CharSet.Contains(X, 'a')); println(CharSet.Contains(Y, 'a')); var Z = X + Y; println(Z); Z = X - Y; println(Z); Z = X * Y; println(Z);