# Collections

## Cheat Sheet

OPERATION VEC DICT KEYSET
Initialize empty \$v = vec[]; \$d = dict[]; \$k = keyset[];
Literal \$v = vec[1, 2, 3]; \$d = dict[‘foo’ => 1]; \$k = keyset[‘foo’, ‘bar’];
From Another Container* \$v = vec(\$container); \$d = dict(\$keyed_container); \$k = keyset(\$container);
Keys from Container* \$v = Vec\keys(\$container); N/A \$k = Keyset\keys(\$container);
Add Elements \$v[] = 4; \$d[‘baz’] = 2; \$k[] = ‘baz’;
Bulk Add Elements \$v = Vec\concat(\$t1, \$t2) \$d = Dict\merge(\$kt1, \$kt2) \$k = Keyset\union(\$t1, \$t2)
Remove Elements Remove-at-index is unsupported; Vec\drop(\$v,\$n), Vec\take(\$v,\$n); \$first=C\pop_front(inout \$x), \$last=C\pop_back(inout \$x) unset(\$d[‘baz’]); unset(\$k[‘baz’]);
Key Existence C\contains_key(\$v, 1) C\contains_key(\$d, ‘foo’) C\contains_key(\$k, ‘foo’)
Value Existence C\contains(\$v, 3) C\contains(\$d, 2) Use C\contains_key(\$k, ‘foo’)
Equality (Order-Dependent) \$v1 === \$v2 \$d1 === \$d2 \$k1 === \$k2
Equality (Order-Independent) N/A Dict\equal(\$d1, \$d2) Keyset\equal(\$k1, \$k2)
Count Elements (i.e., length, size of array) C\count(\$v) C\count(\$d) C\count(\$k)
Type Signature vec dict<Tk, Tv> keyset
Type Refinement \$v is vec<_> \$d is dict<_, _> \$k is keyset<_>
Awaitable Consolidation Vec\from_async(\$v) Dict\from_async(\$d) Keyset\from_async(\$x)

# Types

## Generic Types:

``````class StackUnderflowException extends \Exception {}

class Stack<T> {
private vec<T> \$stack;
private int \$stackPtr;

public function __construct() {
\$this->stackPtr = 0;
\$this->stack = vec[];
}

public function push(T \$value): void {
\$this->stack[] = \$value;
\$this->stackPtr++;
}

public function pop(): T {
if (\$this->stackPtr > 0) {
\$this->stackPtr--;
return \$this->stack[\$this->stackPtr];
} else {
throw new StackUnderflowException();
}
}
}

function use_int_stack(Stack<int> \$stInt): void {
\$stInt->push(10);
\$stInt->push(20);
\$stInt->push(30);
echo 'pop => '.\$stInt->pop()."\n";
}
``````

## Nullable Types

A type ?Foo is either a value of type Foo, or null.

``````function takes_nullable_str2(?string \$s): string {
if (\$s is nonnull){
return \$s;
} else {
return "default";
}
}
``````

## Type Alias

``````type Complex = shape('real' => float, 'imag' => float);
newtype Point = (float, float);

function create_Point(float \$x, float \$y): Point {
return tuple(\$x, \$y);
}

function distance(Point \$p1, Point \$p2): float {
\$dx = \$p1 - \$p2;
\$dy = \$p1 - \$p2;
return \sqrt(\$dx*\$dx + \$dy*\$dy);
}
``````

`newtype Counter as int = int;`

The presence of the type constraint as int allows the opaque type to be treated as if it had the type specified by that type constraint, which removes some of the alias’ opaqueness

``````class C {
const type T2 as arraykey = int;
...
}
``````

we have a class-specific type constant that is an alias, which allows a value of type T2 to be used in any context an arraykey is expected. After all, any int value is also an arraykey value.

# Inheritance

## Sealed classes

only classes mentioned in `<__Sealed>` are able to extend